setwd("/home/mbotos/CLUSTER/Environments/2024_07_05_Lea_Lausanne_Hip_Tibia_BRBseq/")
Warning: The working directory was changed to /home/mbotos/CLUSTER/Environments/2024_07_05_Lea_Lausanne_Hip_Tibia_BRBseq inside a notebook chunk. The working directory will be reset when the chunk is finished running. Use the knitr root.dir option in the setup chunk to change the working directory for notebook chunks.

Path to the data: Environments/2024_07_05_Lea_Lausanne_Hip_Tibia_BRBseq

— Import libraries

#library(BiocManager)
rm(list = ls(all.names = TRUE))
gc()
           plot_the_pca  (Mb) gc trigger  (Mb) max used  (Mb)
Ncells  5420921 289.6   10014902 534.9 10014902 534.9
Vcells 12103103  92.4   45814420 349.6 57254624 436.9
.libPaths("/home/mbotos/R/x86_64-pc-linux-gnu-library/4.2/")
# BiocManager::install(c("dorothea"),force=TRUE,ask = TRUE)
# library(dorothea)

library(dplyr)
library(tidyr)
library(edgeR)

— Read tables

matrix_counts_tibia <- read.table(file ="/home/mbotos/CLUSTER/Environments/2024_07_05_Lea_Lausanne_Hip_Tibia_BRBseq/brbseq-nf-pipeline/results/AMP0211/count_matrix/L270524LF01_01.read.counts.sampleIDs.detailed.txt",sep = "\t",header = TRUE)
head(matrix_counts_tibia)
tail(matrix_counts_tibia)
dim(matrix_counts_tibia)
[1] 60669    82
matrix_counts_tibia
matrix_counts_hip <- read.table(file ="/home/mbotos/CLUSTER/Environments/2024_07_05_Lea_Lausanne_Hip_Tibia_BRBseq/brbseq-nf-pipeline/results/AMP0211/count_matrix/L270524LF02_01.read.counts.sampleIDs.detailed.txt",sep = "\t",header = TRUE)
head(matrix_counts_hip)
tail(matrix_counts_hip)
dim(matrix_counts_hip)
[1] 60669    66
matrix_counts_hip
ncol(matrix_counts_tibia)
[1] 82
colnames(matrix_counts_tibia)
 [1] "Gene_id"                            "Gene_name"                          "X80_tibia_non.sclerotic_adipocyte"  "X102_tibia_non.sclerotic_adipocyte"
 [5] "X107_tibia_non.sclerotic_adipocyte" "X130_Tibia_non.sclerotic_adipocyte" "X149_Tibia_non.sclerotic_adipocyte" "X155_Tibia_non.sclerotic_adipocyte"
 [9] "X159_Tibia_non.sclerotic_adipocyte" "X161_Tibia_non.sclerotic_adipocyte" "X144_Tibia_non.sclerotic_adipocyte" "X128_tibia_non.sclerotic_adipocyte"
[13] "X80_tibia_sclerotic_adipocyte"      "X102_tibia_sclerotic_adipocyte"     "X107_tibia_sclerotic_adipocyte"     "X130_Tibia_sclerotic_adipocyte"    
[17] "X149_Tibia_sclerotic_adipocyte"     "X155_Tibia_sclerotic_adipocyte"     "X159_Tibia_sclerotic_adipocyte"     "X161_Tibia_sclerotic_adipocyte"    
[21] "X144_Tibia_sclerotic_adipocyte"     "X128_tibia_sclerotic_adipocyte"     "X80_tibia_non.sclerotic_pellet"     "X102_tibia_non.sclerotic_pellet"   
[25] "X107_tibia_non.sclerotic_pellet"    "X130_Tibia_non.sclerotic_pellet"    "X149_Tibia_non.sclerotic_pellet"    "X155_Tibia_non.sclerotic_pellet"   
[29] "X159_Tibia_non.sclerotic_pellet"    "X161_Tibia_non.sclerotic_pellet"    "X144_Tibia_non.sclerotic_pellet"    "X128_tibia_non.sclerotic_pellet"   
[33] "X80_tibia_sclerotic_pellet"         "X102_tibia_sclerotic_pellet"        "X107_tibia_sclerotic_pellet"        "X130_Tibia_sclerotic_pellet"       
[37] "X149_Tibia_sclerotic_pellet"        "X155_Tibia_sclerotic_pellet"        "X159_Tibia_sclerotic_pellet"        "X161_Tibia_sclerotic_pellet"       
[41] "X144_Tibia_sclerotic_pellet"        "X128_tibia_sclerotic_pellet"        "X104_tibia_non.sclerotic_adipocyte" "X105_tibia_non.sclerotic_adipocyte"
[45] "X109_tibia_non.sclerotic_adipocyte" "X148_Tibia_non.sclerotic_adipocyte" "X151_Tibia_non.sclerotic_adipocyte" "X156_Tibia_non.sclerotic_adipocyte"
[49] "X160_Tibia_non.sclerotic_adipocyte" "X163_Tibia_non.sclerotic_adipocyte" "X164_tibia_non.sclerotic_adipocyte" "X99_Tibia_non.sclerotic_adipocyte" 
[53] "X104_tibia_sclerotic_adipocyte"     "X105_tibia_sclerotic_adipocyte"     "X109_tibia_sclerotic_adipocyte"     "X148_Tibia_sclerotic_adipocyte"    
[57] "X151_Tibia_sclerotic_adipocyte"     "X156_Tibia_sclerotic_adipocyte"     "X160_Tibia_sclerotic_adipocyte"     "X163_Tibia_sclerotic_adipocyte"    
[61] "X164_tibia_sclerotic_adipocyte"     "X99_Tibia_sclerotic_adipocyte"      "X104_tibia_non.sclerotic_pellet"    "X105_tibia_non.sclerotic_pellet"   
[65] "X109_tibia_non.sclerotic_pellet"    "X148_Tibia_non.sclerotic_pellet"    "X151_Tibia_non.sclerotic_pellet"    "X156_Tibia_non.sclerotic_pellet"   
[69] "X160_Tibia_non.sclerotic_pellet"    "X163_Tibia_non.sclerotic_pellet"    "X164_tibia_non.sclerotic_pellet"    "X99_Tibia_non.sclerotic_pellet"    
[73] "X104_tibia_sclerotic_pellet"        "X105_tibia_sclerotic_pellet"        "X109_tibia_sclerotic_pellet"        "X148_Tibia_sclerotic_pellet"       
[77] "X151_Tibia_sclerotic_pellet"        "X156_Tibia_sclerotic_pellet"        "X160_Tibia_sclerotic_pellet"        "X163_Tibia_sclerotic_pellet"       
[81] "X164_tibia_sclerotic_pellet"        "X99_Tibia_sclerotic_pellet"        
ncol(matrix_counts_hip)
[1] 66
colnames(matrix_counts_hip)
 [1] "Gene_id"                          "Gene_name"                        "X74_Hip_non.sclerotic_adipocyte"  "X79_Hip_non.sclerotic_adipocyte" 
 [5] "X125_Hip_non.sclerotic_adipocyte" "X129_Hip_non.sclerotic_adipocyte" "X145_Hip_non.sclerotic_adipocyte" "X150_Hip_non.sclerotic_adipocyte"
 [9] "X153_Hip_non.sclerotic_adipocyte" "X157_Hip_non.sclerotic_adipocyte" "X74_Hip_sclerotic_adipocyte"      "X79_Hip_sclerotic_adipocyte"     
[13] "X125_Hip_sclerotic_adipocyte"     "X129_Hip_sclerotic_adipocyte"     "X145_Hip_sclerotic_adipocyte"     "X150_Hip_sclerotic_adipocyte"    
[17] "X153_Hip_sclerotic_adipocyte"     "X157_Hip_sclerotic_adipocyte"     "X74_Hip_non.sclerotic_pellet"     "X79_Hip_non.sclerotic_pellet"    
[21] "X125_Hip_non.sclerotic_pellet"    "X129_Hip_non.sclerotic_pellet"    "X145_Hip_non.sclerotic_pellet"    "X150_Hip_non.sclerotic_pellet"   
[25] "X153_Hip_non.sclerotic_pellet"    "X157_Hip_non.sclerotic_pellet"    "X74_Hip_sclerotic_pellet"         "X79_Hip_sclerotic_pellet"        
[29] "X125_Hip_sclerotic_pellet"        "X129_Hip_sclerotic_pellet"        "X145_Hip_sclerotic_pellet"        "X150_Hip_sclerotic_pellet"       
[33] "X153_Hip_sclerotic_pellet"        "X157_Hip_sclerotic_pellet"        "X78_Hip_non.sclerotic_adipocyte"  "X108_Hip_non.sclerotic_adipocyte"
[37] "X126_Hip_non.sclerotic_adipocyte" "X143_Hip_non.sclerotic_adipocyte" "X146_Hip_non.sclerotic_adipocyte" "X152_Hip_non.sclerotic_adipocyte"
[41] "X154_Hip_non.sclerotic_adipocyte" "X158_Hip_non.sclerotic_adipocyte" "X78_Hip_sclerotic_adipocyte"      "X108_Hip_sclerotic_adipocyte"    
[45] "X126_Hip_sclerotic_adipocyte"     "X143_Hip_sclerotic_adipocyte"     "X146_Hip_sclerotic_adipocyte"     "X152_Hip_sclerotic_adipocyte"    
[49] "X154_Hip_sclerotic_adipocyte"     "X158_Hip_sclerotic_adipocyte"     "X78_Hip_non.sclerotic_pellet"     "X108_Hip_non.sclerotic_pellet"   
[53] "X126_Hip_non.sclerotic_pellet"    "X143_Hip_non.sclerotic_pellet"    "X146_Hip_non.sclerotic_pellet"    "X152_Hip_non.sclerotic_pellet"   
[57] "X154_Hip_non.sclerotic_pellet"    "X158_Hip_non.sclerotic_pellet"    "X78_Hip_sclerotic_pellet"         "X108_Hip_sclerotic_pellet"       
[61] "X126_Hip_sclerotic_pellet"        "X143_Hip_sclerotic_pellet"        "X146_Hip_sclerotic_pellet"        "X152_Hip_sclerotic_pellet"       
[65] "X154_Hip_sclerotic_pellet"        "X158_Hip_sclerotic_pellet"       
# Remove the last column
# New version do not need to be removed, Uknown columns is not there anymore...
#the Gene_id or Gene_name which are in the position 1 and 2

#matrix_counts <- matrix_counts[,-ncol(matrix_counts)]

# Remove the last 5 rows
matrix_counts_tibia <- matrix_counts_tibia[1:(nrow(matrix_counts_tibia)-5),]
head(matrix_counts_tibia)
tail(matrix_counts_tibia)
dim(matrix_counts_tibia)
[1] 60664    82
colnames(matrix_counts_tibia)[3:ncol(matrix_counts_tibia)]
 [1] "X80_tibia_non.sclerotic_adipocyte"  "X102_tibia_non.sclerotic_adipocyte" "X107_tibia_non.sclerotic_adipocyte" "X130_Tibia_non.sclerotic_adipocyte"
 [5] "X149_Tibia_non.sclerotic_adipocyte" "X155_Tibia_non.sclerotic_adipocyte" "X159_Tibia_non.sclerotic_adipocyte" "X161_Tibia_non.sclerotic_adipocyte"
 [9] "X144_Tibia_non.sclerotic_adipocyte" "X128_tibia_non.sclerotic_adipocyte" "X80_tibia_sclerotic_adipocyte"      "X102_tibia_sclerotic_adipocyte"    
[13] "X107_tibia_sclerotic_adipocyte"     "X130_Tibia_sclerotic_adipocyte"     "X149_Tibia_sclerotic_adipocyte"     "X155_Tibia_sclerotic_adipocyte"    
[17] "X159_Tibia_sclerotic_adipocyte"     "X161_Tibia_sclerotic_adipocyte"     "X144_Tibia_sclerotic_adipocyte"     "X128_tibia_sclerotic_adipocyte"    
[21] "X80_tibia_non.sclerotic_pellet"     "X102_tibia_non.sclerotic_pellet"    "X107_tibia_non.sclerotic_pellet"    "X130_Tibia_non.sclerotic_pellet"   
[25] "X149_Tibia_non.sclerotic_pellet"    "X155_Tibia_non.sclerotic_pellet"    "X159_Tibia_non.sclerotic_pellet"    "X161_Tibia_non.sclerotic_pellet"   
[29] "X144_Tibia_non.sclerotic_pellet"    "X128_tibia_non.sclerotic_pellet"    "X80_tibia_sclerotic_pellet"         "X102_tibia_sclerotic_pellet"       
[33] "X107_tibia_sclerotic_pellet"        "X130_Tibia_sclerotic_pellet"        "X149_Tibia_sclerotic_pellet"        "X155_Tibia_sclerotic_pellet"       
[37] "X159_Tibia_sclerotic_pellet"        "X161_Tibia_sclerotic_pellet"        "X144_Tibia_sclerotic_pellet"        "X128_tibia_sclerotic_pellet"       
[41] "X104_tibia_non.sclerotic_adipocyte" "X105_tibia_non.sclerotic_adipocyte" "X109_tibia_non.sclerotic_adipocyte" "X148_Tibia_non.sclerotic_adipocyte"
[45] "X151_Tibia_non.sclerotic_adipocyte" "X156_Tibia_non.sclerotic_adipocyte" "X160_Tibia_non.sclerotic_adipocyte" "X163_Tibia_non.sclerotic_adipocyte"
[49] "X164_tibia_non.sclerotic_adipocyte" "X99_Tibia_non.sclerotic_adipocyte"  "X104_tibia_sclerotic_adipocyte"     "X105_tibia_sclerotic_adipocyte"    
[53] "X109_tibia_sclerotic_adipocyte"     "X148_Tibia_sclerotic_adipocyte"     "X151_Tibia_sclerotic_adipocyte"     "X156_Tibia_sclerotic_adipocyte"    
[57] "X160_Tibia_sclerotic_adipocyte"     "X163_Tibia_sclerotic_adipocyte"     "X164_tibia_sclerotic_adipocyte"     "X99_Tibia_sclerotic_adipocyte"     
[61] "X104_tibia_non.sclerotic_pellet"    "X105_tibia_non.sclerotic_pellet"    "X109_tibia_non.sclerotic_pellet"    "X148_Tibia_non.sclerotic_pellet"   
[65] "X151_Tibia_non.sclerotic_pellet"    "X156_Tibia_non.sclerotic_pellet"    "X160_Tibia_non.sclerotic_pellet"    "X163_Tibia_non.sclerotic_pellet"   
[69] "X164_tibia_non.sclerotic_pellet"    "X99_Tibia_non.sclerotic_pellet"     "X104_tibia_sclerotic_pellet"        "X105_tibia_sclerotic_pellet"       
[73] "X109_tibia_sclerotic_pellet"        "X148_Tibia_sclerotic_pellet"        "X151_Tibia_sclerotic_pellet"        "X156_Tibia_sclerotic_pellet"       
[77] "X160_Tibia_sclerotic_pellet"        "X163_Tibia_sclerotic_pellet"        "X164_tibia_sclerotic_pellet"        "X99_Tibia_sclerotic_pellet"        
# Remove the last 5 rows
matrix_counts_hip <- matrix_counts_hip[1:(nrow(matrix_counts_hip)-5),]
head(matrix_counts_hip)
tail(matrix_counts_hip)
dim(matrix_counts_hip)
[1] 60664    66
colnames(matrix_counts_hip)[3:ncol(matrix_counts_hip)]
 [1] "X74_Hip_non.sclerotic_adipocyte"  "X79_Hip_non.sclerotic_adipocyte"  "X125_Hip_non.sclerotic_adipocyte" "X129_Hip_non.sclerotic_adipocyte"
 [5] "X145_Hip_non.sclerotic_adipocyte" "X150_Hip_non.sclerotic_adipocyte" "X153_Hip_non.sclerotic_adipocyte" "X157_Hip_non.sclerotic_adipocyte"
 [9] "X74_Hip_sclerotic_adipocyte"      "X79_Hip_sclerotic_adipocyte"      "X125_Hip_sclerotic_adipocyte"     "X129_Hip_sclerotic_adipocyte"    
[13] "X145_Hip_sclerotic_adipocyte"     "X150_Hip_sclerotic_adipocyte"     "X153_Hip_sclerotic_adipocyte"     "X157_Hip_sclerotic_adipocyte"    
[17] "X74_Hip_non.sclerotic_pellet"     "X79_Hip_non.sclerotic_pellet"     "X125_Hip_non.sclerotic_pellet"    "X129_Hip_non.sclerotic_pellet"   
[21] "X145_Hip_non.sclerotic_pellet"    "X150_Hip_non.sclerotic_pellet"    "X153_Hip_non.sclerotic_pellet"    "X157_Hip_non.sclerotic_pellet"   
[25] "X74_Hip_sclerotic_pellet"         "X79_Hip_sclerotic_pellet"         "X125_Hip_sclerotic_pellet"        "X129_Hip_sclerotic_pellet"       
[29] "X145_Hip_sclerotic_pellet"        "X150_Hip_sclerotic_pellet"        "X153_Hip_sclerotic_pellet"        "X157_Hip_sclerotic_pellet"       
[33] "X78_Hip_non.sclerotic_adipocyte"  "X108_Hip_non.sclerotic_adipocyte" "X126_Hip_non.sclerotic_adipocyte" "X143_Hip_non.sclerotic_adipocyte"
[37] "X146_Hip_non.sclerotic_adipocyte" "X152_Hip_non.sclerotic_adipocyte" "X154_Hip_non.sclerotic_adipocyte" "X158_Hip_non.sclerotic_adipocyte"
[41] "X78_Hip_sclerotic_adipocyte"      "X108_Hip_sclerotic_adipocyte"     "X126_Hip_sclerotic_adipocyte"     "X143_Hip_sclerotic_adipocyte"    
[45] "X146_Hip_sclerotic_adipocyte"     "X152_Hip_sclerotic_adipocyte"     "X154_Hip_sclerotic_adipocyte"     "X158_Hip_sclerotic_adipocyte"    
[49] "X78_Hip_non.sclerotic_pellet"     "X108_Hip_non.sclerotic_pellet"    "X126_Hip_non.sclerotic_pellet"    "X143_Hip_non.sclerotic_pellet"   
[53] "X146_Hip_non.sclerotic_pellet"    "X152_Hip_non.sclerotic_pellet"    "X154_Hip_non.sclerotic_pellet"    "X158_Hip_non.sclerotic_pellet"   
[57] "X78_Hip_sclerotic_pellet"         "X108_Hip_sclerotic_pellet"        "X126_Hip_sclerotic_pellet"        "X143_Hip_sclerotic_pellet"       
[61] "X146_Hip_sclerotic_pellet"        "X152_Hip_sclerotic_pellet"        "X154_Hip_sclerotic_pellet"        "X158_Hip_sclerotic_pellet"       

Maybe later we need to divide it into Adipo,Pellet from Tibias and Hips

# wrong_names <- c("mHH3.12P15...F3neg","mHH3.12P28.EW...F3neg","mHH3.12P28.Ctrl...F3neg")
# colnames(matrix_counts)[3:104] <- gsub(x = colnames(matrix_counts)[3:104],pattern = "F3.$",replacement = "F3+")
# for (wrong_name in wrong_names){
#   correct_name <- gsub(pattern = "P",replacement = ".P",x = wrong_name)
#   colnames(matrix_counts)[colnames(matrix_counts) == wrong_name] <- correct_name
# }
# 
# 
# matrix_aspcs <- matrix_counts[3:ncol(matrix_counts)] |> dplyr::select(matches("ASPCs"))
# matrix_f3pos <- matrix_counts[3:ncol(matrix_counts)] |> dplyr::select(ends_with("F3+",))
# matrix_f3neg <- matrix_counts[3:ncol(matrix_counts)] |> dplyr::select(ends_with("F3neg"))

— Add metadata table from the xlsx file

md <- readxl::read_xlsx(path ="/home/mbotos/CLUSTER/Environments/2024_07_05_Lea_Lausanne_Hip_Tibia_BRBseq/Analysis/metadata/sample_info_minimal_SIT.xlsx")
New names:
• `RIN...13` -> `RIN...17`
• `RIN...20` -> `RIN...24`
md$sampleID
  [1] "80_tibia_non sclerotic_adipocyte"  "102_tibia_non sclerotic_adipocyte" "107_tibia_non sclerotic_adipocyte" "130_Tibia_non sclerotic_adipocyte"
  [5] "149_Tibia_non sclerotic_adipocyte" "155_Tibia_non sclerotic_adipocyte" "159_Tibia_non sclerotic_adipocyte" "161_Tibia_non sclerotic_adipocyte"
  [9] "144_Tibia_non sclerotic_adipocyte" "128_tibia_non sclerotic_adipocyte" "80_tibia_sclerotic_adipocyte"      "102_tibia_sclerotic_adipocyte"    
 [13] "107_tibia_sclerotic_adipocyte"     "130_Tibia_sclerotic_adipocyte"     "149_Tibia_sclerotic_adipocyte"     "155_Tibia_sclerotic_adipocyte"    
 [17] "159_Tibia_sclerotic_adipocyte"     "161_Tibia_sclerotic_adipocyte"     "144_Tibia_sclerotic_adipocyte"     "128_tibia_sclerotic_adipocyte"    
 [21] "80_tibia_non sclerotic_pellet"     "102_tibia_non sclerotic_pellet"    "107_tibia_non sclerotic_pellet"    "130_Tibia_non sclerotic_pellet"   
 [25] "149_Tibia_non sclerotic_pellet"    "155_Tibia_non sclerotic_pellet"    "159_Tibia_non sclerotic_pellet"    "161_Tibia_non sclerotic_pellet"   
 [29] "144_Tibia_non sclerotic_pellet"    "128_tibia_non sclerotic_pellet"    "80_tibia_sclerotic_pellet"         "102_tibia_sclerotic_pellet"       
 [33] "107_tibia_sclerotic_pellet"        "130_Tibia_sclerotic_pellet"        "149_Tibia_sclerotic_pellet"        "155_Tibia_sclerotic_pellet"       
 [37] "159_Tibia_sclerotic_pellet"        "161_Tibia_sclerotic_pellet"        "144_Tibia_sclerotic_pellet"        "128_tibia_sclerotic_pellet"       
 [41] "104_tibia_non sclerotic_adipocyte" "105_tibia_non sclerotic_adipocyte" "109_tibia_non sclerotic_adipocyte" "148_Tibia_non sclerotic_adipocyte"
 [45] "151_Tibia_non sclerotic_adipocyte" "156_Tibia_non sclerotic_adipocyte" "160_Tibia_non sclerotic_adipocyte" "163_Tibia_non sclerotic_adipocyte"
 [49] "164_tibia_non sclerotic_adipocyte" "99_Tibia_non sclerotic_adipocyte"  "104_tibia_sclerotic_adipocyte"     "105_tibia_sclerotic_adipocyte"    
 [53] "109_tibia_sclerotic_adipocyte"     "148_Tibia_sclerotic_adipocyte"     "151_Tibia_sclerotic_adipocyte"     "156_Tibia_sclerotic_adipocyte"    
 [57] "160_Tibia_sclerotic_adipocyte"     "163_Tibia_sclerotic_adipocyte"     "164_tibia_sclerotic_adipocyte"     "99_Tibia_sclerotic_adipocyte"     
 [61] "104_tibia_non sclerotic_pellet"    "105_tibia_non sclerotic_pellet"    "109_tibia_non sclerotic_pellet"    "148_Tibia_non sclerotic_pellet"   
 [65] "151_Tibia_non sclerotic_pellet"    "156_Tibia_non sclerotic_pellet"    "160_Tibia_non sclerotic_pellet"    "163_Tibia_non sclerotic_pellet"   
 [69] "164_tibia_non sclerotic_pellet"    "99_Tibia_non sclerotic_pellet"     "104_tibia_sclerotic_pellet"        "105_tibia_sclerotic_pellet"       
 [73] "109_tibia_sclerotic_pellet"        "148_Tibia_sclerotic_pellet"        "151_Tibia_sclerotic_pellet"        "156_Tibia_sclerotic_pellet"       
 [77] "160_Tibia_sclerotic_pellet"        "163_Tibia_sclerotic_pellet"        "164_tibia_sclerotic_pellet"        "99_Tibia_sclerotic_pellet"        
 [81] "74_Hip_non sclerotic_adipocyte"    "79_Hip_non sclerotic_adipocyte"    "125_Hip_non sclerotic_adipocyte"   "129_Hip_non sclerotic_adipocyte"  
 [85] "145_Hip_non sclerotic_adipocyte"   "150_Hip_non sclerotic_adipocyte"   "153_Hip_non sclerotic_adipocyte"   "157_Hip_non sclerotic_adipocyte"  
 [89] "74_Hip_sclerotic_adipocyte"        "79_Hip_sclerotic_adipocyte"        "125_Hip_sclerotic_adipocyte"       "129_Hip_sclerotic_adipocyte"      
 [93] "145_Hip_sclerotic_adipocyte"       "150_Hip_sclerotic_adipocyte"       "153_Hip_sclerotic_adipocyte"       "157_Hip_sclerotic_adipocyte"      
 [97] "74_Hip_non sclerotic_pellet"       "79_Hip_non sclerotic_pellet"       "125_Hip_non sclerotic_pellet"      "129_Hip_non sclerotic_pellet"     
[101] "145_Hip_non sclerotic_pellet"      "150_Hip_non sclerotic_pellet"      "153_Hip_non sclerotic_pellet"      "157_Hip_non sclerotic_pellet"     
[105] "74_Hip_sclerotic_pellet"           "79_Hip_sclerotic_pellet"           "125_Hip_sclerotic_pellet"          "129_Hip_sclerotic_pellet"         
[109] "145_Hip_sclerotic_pellet"          "150_Hip_sclerotic_pellet"          "153_Hip_sclerotic_pellet"          "157_Hip_sclerotic_pellet"         
[113] "78_Hip_non sclerotic_adipocyte"    "108_Hip_non sclerotic_adipocyte"   "126_Hip_non sclerotic_adipocyte"   "143_Hip_non sclerotic_adipocyte"  
[117] "146_Hip_non sclerotic_adipocyte"   "152_Hip_non sclerotic_adipocyte"   "154_Hip_non sclerotic_adipocyte"   "158_Hip_non sclerotic_adipocyte"  
[121] "78_Hip_sclerotic_adipocyte"        "108_Hip_sclerotic_adipocyte"       "126_Hip_sclerotic_adipocyte"       "143_Hip_sclerotic_adipocyte"      
[125] "146_Hip_sclerotic_adipocyte"       "152_Hip_sclerotic_adipocyte"       "154_Hip_sclerotic_adipocyte"       "158_Hip_sclerotic_adipocyte"      
[129] "78_Hip_non sclerotic_pellet"       "108_Hip_non sclerotic_pellet"      "126_Hip_non sclerotic_pellet"      "143_Hip_non sclerotic_pellet"     
[133] "146_Hip_non sclerotic_pellet"      "152_Hip_non sclerotic_pellet"      "154_Hip_non sclerotic_pellet"      "158_Hip_non sclerotic_pellet"     
[137] "78_Hip_sclerotic_pellet"           "108_Hip_sclerotic_pellet"          "126_Hip_sclerotic_pellet"          "143_Hip_sclerotic_pellet"         
[141] "146_Hip_sclerotic_pellet"          "152_Hip_sclerotic_pellet"          "154_Hip_sclerotic_pellet"          "158_Hip_sclerotic_pellet"         

# Use mutate to format the sample IDs
md_df <- md %>% 
  dplyr::mutate(sampleID = gsub(" ", ".", sampleID)) %>%
  dplyr::mutate(sampleID = paste0("X", sampleID))

# Display the data frame with formatted sample IDs
print(md_df)
md
md_df
NA

Generate more columns for the data to plot

md_df$sampleID
  [1] "X80_tibia_non.sclerotic_adipocyte"  "X102_tibia_non.sclerotic_adipocyte" "X107_tibia_non.sclerotic_adipocyte" "X130_Tibia_non.sclerotic_adipocyte"
  [5] "X149_Tibia_non.sclerotic_adipocyte" "X155_Tibia_non.sclerotic_adipocyte" "X159_Tibia_non.sclerotic_adipocyte" "X161_Tibia_non.sclerotic_adipocyte"
  [9] "X144_Tibia_non.sclerotic_adipocyte" "X128_tibia_non.sclerotic_adipocyte" "X80_tibia_sclerotic_adipocyte"      "X102_tibia_sclerotic_adipocyte"    
 [13] "X107_tibia_sclerotic_adipocyte"     "X130_Tibia_sclerotic_adipocyte"     "X149_Tibia_sclerotic_adipocyte"     "X155_Tibia_sclerotic_adipocyte"    
 [17] "X159_Tibia_sclerotic_adipocyte"     "X161_Tibia_sclerotic_adipocyte"     "X144_Tibia_sclerotic_adipocyte"     "X128_tibia_sclerotic_adipocyte"    
 [21] "X80_tibia_non.sclerotic_pellet"     "X102_tibia_non.sclerotic_pellet"    "X107_tibia_non.sclerotic_pellet"    "X130_Tibia_non.sclerotic_pellet"   
 [25] "X149_Tibia_non.sclerotic_pellet"    "X155_Tibia_non.sclerotic_pellet"    "X159_Tibia_non.sclerotic_pellet"    "X161_Tibia_non.sclerotic_pellet"   
 [29] "X144_Tibia_non.sclerotic_pellet"    "X128_tibia_non.sclerotic_pellet"    "X80_tibia_sclerotic_pellet"         "X102_tibia_sclerotic_pellet"       
 [33] "X107_tibia_sclerotic_pellet"        "X130_Tibia_sclerotic_pellet"        "X149_Tibia_sclerotic_pellet"        "X155_Tibia_sclerotic_pellet"       
 [37] "X159_Tibia_sclerotic_pellet"        "X161_Tibia_sclerotic_pellet"        "X144_Tibia_sclerotic_pellet"        "X128_tibia_sclerotic_pellet"       
 [41] "X104_tibia_non.sclerotic_adipocyte" "X105_tibia_non.sclerotic_adipocyte" "X109_tibia_non.sclerotic_adipocyte" "X148_Tibia_non.sclerotic_adipocyte"
 [45] "X151_Tibia_non.sclerotic_adipocyte" "X156_Tibia_non.sclerotic_adipocyte" "X160_Tibia_non.sclerotic_adipocyte" "X163_Tibia_non.sclerotic_adipocyte"
 [49] "X164_tibia_non.sclerotic_adipocyte" "X99_Tibia_non.sclerotic_adipocyte"  "X104_tibia_sclerotic_adipocyte"     "X105_tibia_sclerotic_adipocyte"    
 [53] "X109_tibia_sclerotic_adipocyte"     "X148_Tibia_sclerotic_adipocyte"     "X151_Tibia_sclerotic_adipocyte"     "X156_Tibia_sclerotic_adipocyte"    
 [57] "X160_Tibia_sclerotic_adipocyte"     "X163_Tibia_sclerotic_adipocyte"     "X164_tibia_sclerotic_adipocyte"     "X99_Tibia_sclerotic_adipocyte"     
 [61] "X104_tibia_non.sclerotic_pellet"    "X105_tibia_non.sclerotic_pellet"    "X109_tibia_non.sclerotic_pellet"    "X148_Tibia_non.sclerotic_pellet"   
 [65] "X151_Tibia_non.sclerotic_pellet"    "X156_Tibia_non.sclerotic_pellet"    "X160_Tibia_non.sclerotic_pellet"    "X163_Tibia_non.sclerotic_pellet"   
 [69] "X164_tibia_non.sclerotic_pellet"    "X99_Tibia_non.sclerotic_pellet"     "X104_tibia_sclerotic_pellet"        "X105_tibia_sclerotic_pellet"       
 [73] "X109_tibia_sclerotic_pellet"        "X148_Tibia_sclerotic_pellet"        "X151_Tibia_sclerotic_pellet"        "X156_Tibia_sclerotic_pellet"       
 [77] "X160_Tibia_sclerotic_pellet"        "X163_Tibia_sclerotic_pellet"        "X164_tibia_sclerotic_pellet"        "X99_Tibia_sclerotic_pellet"        
 [81] "X74_Hip_non.sclerotic_adipocyte"    "X79_Hip_non.sclerotic_adipocyte"    "X125_Hip_non.sclerotic_adipocyte"   "X129_Hip_non.sclerotic_adipocyte"  
 [85] "X145_Hip_non.sclerotic_adipocyte"   "X150_Hip_non.sclerotic_adipocyte"   "X153_Hip_non.sclerotic_adipocyte"   "X157_Hip_non.sclerotic_adipocyte"  
 [89] "X74_Hip_sclerotic_adipocyte"        "X79_Hip_sclerotic_adipocyte"        "X125_Hip_sclerotic_adipocyte"       "X129_Hip_sclerotic_adipocyte"      
 [93] "X145_Hip_sclerotic_adipocyte"       "X150_Hip_sclerotic_adipocyte"       "X153_Hip_sclerotic_adipocyte"       "X157_Hip_sclerotic_adipocyte"      
 [97] "X74_Hip_non.sclerotic_pellet"       "X79_Hip_non.sclerotic_pellet"       "X125_Hip_non.sclerotic_pellet"      "X129_Hip_non.sclerotic_pellet"     
[101] "X145_Hip_non.sclerotic_pellet"      "X150_Hip_non.sclerotic_pellet"      "X153_Hip_non.sclerotic_pellet"      "X157_Hip_non.sclerotic_pellet"     
[105] "X74_Hip_sclerotic_pellet"           "X79_Hip_sclerotic_pellet"           "X125_Hip_sclerotic_pellet"          "X129_Hip_sclerotic_pellet"         
[109] "X145_Hip_sclerotic_pellet"          "X150_Hip_sclerotic_pellet"          "X153_Hip_sclerotic_pellet"          "X157_Hip_sclerotic_pellet"         
[113] "X78_Hip_non.sclerotic_adipocyte"    "X108_Hip_non.sclerotic_adipocyte"   "X126_Hip_non.sclerotic_adipocyte"   "X143_Hip_non.sclerotic_adipocyte"  
[117] "X146_Hip_non.sclerotic_adipocyte"   "X152_Hip_non.sclerotic_adipocyte"   "X154_Hip_non.sclerotic_adipocyte"   "X158_Hip_non.sclerotic_adipocyte"  
[121] "X78_Hip_sclerotic_adipocyte"        "X108_Hip_sclerotic_adipocyte"       "X126_Hip_sclerotic_adipocyte"       "X143_Hip_sclerotic_adipocyte"      
[125] "X146_Hip_sclerotic_adipocyte"       "X152_Hip_sclerotic_adipocyte"       "X154_Hip_sclerotic_adipocyte"       "X158_Hip_sclerotic_adipocyte"      
[129] "X78_Hip_non.sclerotic_pellet"       "X108_Hip_non.sclerotic_pellet"      "X126_Hip_non.sclerotic_pellet"      "X143_Hip_non.sclerotic_pellet"     
[133] "X146_Hip_non.sclerotic_pellet"      "X152_Hip_non.sclerotic_pellet"      "X154_Hip_non.sclerotic_pellet"      "X158_Hip_non.sclerotic_pellet"     
[137] "X78_Hip_sclerotic_pellet"           "X108_Hip_sclerotic_pellet"          "X126_Hip_sclerotic_pellet"          "X143_Hip_sclerotic_pellet"         
[141] "X146_Hip_sclerotic_pellet"          "X152_Hip_sclerotic_pellet"          "X154_Hip_sclerotic_pellet"          "X158_Hip_sclerotic_pellet"         
# Split the sampleID column
md_df_split <- strsplit(as.character(md_df$sampleID), "_", fixed = TRUE)

# Create new columns
md_df$sample_number <- sapply(md_df_split, function(x) x[1])
md_df$tissue <- sapply(md_df_split, function(x) x[2])
#md_df$health_status <- sapply(md_df_split, function(x) paste(x[3], x[4], sep = "_"))
md_df$health_status <- sapply(md_df_split, function(x) paste(x[3], sep = "_"))
md_df$tissue_celltype <- sapply(md_df_split, function(x) paste(x[4], sep = "_"))
md_df$tissue_celltype_lowercase <- tolower(md_df$tissue_celltype)
md_df$tissue_lowercase <- tolower(md_df$tissue)
md_df$full_name <- md_df$sampleID


# View the dataframe
md_df
NA

Add gender, age and BMI to metadata.

agbmi_df <- readxl::read_xlsx(path ="/home/mbotos/CLUSTER/Environments/2024_07_05_Lea_Lausanne_Hip_Tibia_BRBseq/Analysis/metadata/age-gender-BRBseq.xlsx")
agbmi_df

# Add X infront of the sample ID and close non sclerotic with non.sclerotic.

agbmi_df <- agbmi_df |>  
  dplyr::mutate(`Sample ID` = gsub(" ", ".", `Sample ID`)) |> 
  dplyr::mutate(`Sample ID` = paste0("X", `Sample ID`))
agbmi_df

md_df <- merge(x = md_df,y = agbmi_df,by.x = "sampleID",by.y = "Sample ID")

Orientation of Data

Transposed Data (samples as rows, genes as columns)

m <- prcomp(t(matrix_counts_hip[,3:ncol(matrix_counts_hip)]), scale. = TRUE, center = TRUE) Input Matrix: After transposing, each row represents a sample, and each column represents a gene. Interpretation: PCA will identify principal components based on the variance among samples across different genes. Results: The principal components will describe the variation between the samples. Each principal component (PC) is a linear combination of the gene expression values.

Non-Transposed Data (genes as rows, samples as columns)

m <- prcomp(matrix_counts_hip[,3:ncol(matrix_counts_hip)], scale. = TRUE, center = TRUE) Input Matrix: Without transposing, each row represents a gene, and each column represents a sample. Interpretation: PCA will identify principal components based on the variance among genes across different samples. Results: The principal components will describe the variation between the genes. Each principal component (PC) is a linear combination of the sample values.

Choosing the Right Approach

The choice of whether to transpose the data or not depends on what you want to analyze:

Analyzing Variation Between Samples: If your goal is to analyze how samples (conditions) vary based on gene expression profiles, you should transpose the data so that each row represents a sample. This will provide principal components that describe the differences between samples.

m <- prcomp(t(matrix_counts_hip[,3:ncol(matrix_counts_hip)]), scale. = TRUE, center = TRUE)

Analyzing Variation Between Genes: If your goal is to analyze how genes vary across different samples, you should not transpose the data, keeping genes as rows and samples as columns. This will provide principal components that describe the differences between genes.

m <- prcomp(matrix_counts_hip[,3:ncol(matrix_counts_hip)], scale. = TRUE, center = TRUE)

Clean rows that have gene expression for all the samples < 3 counts.

# If no results of DEG obtained, we reduce stringency, so lower the number.

ncol(matrix_counts_hip)
[1] 66
dim(matrix_counts_hip[,3:ncol(matrix_counts_hip)][rowSums(matrix_counts_hip[,3:ncol(matrix_counts_hip)]) >= 30,])
[1] 25139    64
dim(matrix_counts_tibia[,3:ncol(matrix_counts_tibia)][rowSums(matrix_counts_tibia[,3:ncol(matrix_counts_tibia)]) >= 30,])
[1] 25993    80
# row_sums <- rowSums(matrix_counts_hip[, 3:ncol(matrix_counts_hip)])
# matrix_counts_hip_filtered <- matrix_counts_hip[row_sums >= 30,]
# matrix_counts_hip_filtered

#Function for PCA, removing empty genes counts and empty columns if trnasposed.

run_pca_structuring <- function(matrix_data, transpose=TRUE,filter_empty_samples_counts=30){
  
  data_matrix_raw <- matrix_data
  data_matrix <- matrix_data[,3:ncol(matrix_data)]
  row_sums = rowSums(data_matrix)
  data_matrix_filtered = data_matrix[row_sums >= filter_empty_samples_counts,]
  
  # 
  # # Remove constant/zero columns
  # non_constant_columns <- apply(data_matrix_filtered, 2, function(x) sd(x) != 0)
  # data_matrix_filtered <- data_matrix_filtered[, non_constant_columns]

  # Check transpose
  if (transpose){
    data_matrix <- t(data_matrix)
  }
  
  #Run PCA
  
  m <- prcomp(data_matrix_filtered,scale. = TRUE,center = TRUE)
  #calculat the PC "%"'s
  percentVar_obj <- m$sdev^2/sum(m$sdev^2)
  
  #Save as a df
  m <- as.data.frame(m[2]$rotation)
  m <- merge(x = m,y = md_df,by.x="row.names",by.y="full_name")
  
  return(list(
    matrix_raw=data_matrix_raw,
    matrix_pca=m,
    percentVar_obj=percentVar_obj))
  
}
#Genes variability, typically biology difference across samples is stronger.. so it is also difficult to catch...
m_pca_tibia <- run_pca_structuring(matrix_data = matrix_counts_tibia,transpose = FALSE,filter_empty_samples_counts = 30)
m_pca_hip <- run_pca_structuring(matrix_data = matrix_counts_hip,transpose = FALSE,filter_empty_samples_counts = 30)

Plot the PCA function

require("ggplot2")
#shapes
plot_the_pca <- function(pca_df,colors,pca,pcb,title,subtitle,colors_selection,shapes,shapes_selection,alphas=0.6,text_column="Row.names",percentVar_obj) {
  
  n <- ggplot(data = pca_df,aes(x = pca_df[[paste0("PC",substr(pca,start = 3,stop = 3))]],
                                y = pca_df[[paste0("PC",substr(pcb,start = 3,stop = 3))]],
                                color = pca_df[[colors]],
                                shape = pca_df[[shapes]]))
  # n <- n + geom_point(size=6)
  n <- n + geom_jitter(position = position_jitter(width = 0.000000001,height = 0.000000001,seed = 123456),size=6,alpha=alphas)
  n <- n + labs(title=paste0("PCA ",title),
                #color = paste0(colors),
                #shape = paste0(shapes),
                subtitle = paste0(subtitle,"")) +
    xlab(paste0("PC",substr(paste0("PC",substr(pca,start = 3,stop = 3)),start = 3,stop = 3),": ",
                round(percentVar_obj[as.numeric(substr(paste0("PC",substr(pca,start = 3,stop = 3)),start = 3,stop = 3))] * 100,digits = 2), "% variance")) +
    ylab(paste0("PC",substr(paste0("PC",substr(pcb,start = 3,stop = 3)),start = 3,stop = 3),": ",
                round(percentVar_obj[as.numeric(substr(paste0("PC",substr(pcb,start = 3,stop = 3)),start = 3,stop = 3))] * 100,digits = 2), "% variance"))
  n <- n + theme(panel.grid = element_blank(),
                 panel.border = element_rect(fill = "transparent"),
                 panel.background = element_rect(fill = "transparent"),
                 legend.title = element_text(size=15),
                 legend.text = element_text(size=12))
  n <- n + geom_text(aes(label = pca_df[[text_column]]),color = "black", size = 2)

  # n <- n + scale_color_manual(values = colors_selection)
  # n <- n + scale_shape_manual(values = shapes_selection)
  n
  
}

— Raw

Tibia

### Need to be run the run_pca_structuring before the plot the pca otherwise the objects mess up
# Generate the columns in the md_df
plot_the_pca(pca_df = m_pca_tibia$matrix_pca,
             percentVar_obj = m_pca_tibia$percentVar_obj,
             colors =  "tissue_celltype_lowercase",shapes = "health_status",
             pca = "PC1",pcb = "PC2",
             title="PCA of RNA-seq Raw Data",subtitle = "Tibias SVF and Adipocytes",
             text_column = "sample_number")
Warning: Use of `pca_df[[paste0("PC", substr(pca, start = 3, stop = 3))]]` is discouraged.
ℹ Use `.data[[paste0("PC", substr(pca, start = 3, stop = 3))]]` instead.
Warning: Use of `pca_df[[paste0("PC", substr(pcb, start = 3, stop = 3))]]` is discouraged.
ℹ Use `.data[[paste0("PC", substr(pcb, start = 3, stop = 3))]]` instead.
Warning: Use of `pca_df[[colors]]` is discouraged.
ℹ Use `.data[[colors]]` instead.
Warning: Use of `pca_df[[shapes]]` is discouraged.
ℹ Use `.data[[shapes]]` instead.
Warning: Use of `pca_df[[text_column]]` is discouraged.
ℹ Use `.data[[text_column]]` instead.
Warning: Use of `pca_df[[paste0("PC", substr(pca, start = 3, stop = 3))]]` is discouraged.
ℹ Use `.data[[paste0("PC", substr(pca, start = 3, stop = 3))]]` instead.
Warning: Use of `pca_df[[paste0("PC", substr(pcb, start = 3, stop = 3))]]` is discouraged.
ℹ Use `.data[[paste0("PC", substr(pcb, start = 3, stop = 3))]]` instead.
Warning: Use of `pca_df[[shapes]]` is discouraged.
ℹ Use `.data[[shapes]]` instead.

Hip

### Need to be run the run_pca_structuring before the plot the pca otherwise the objects mess up
# Generate the columns in the md_df
plot_the_pca(pca_df = m_pca_hip$matrix_pca,
             percentVar_obj = m_pca_hip$percentVar_obj,
             colors =  "tissue_celltype_lowercase",shapes = "health_status",
             pca = "PC1",pcb = "PC2",
             title="PCA of RNA-seq Raw Data",subtitle = "Hips SVF and Adipocytes",
             text_column = "sample_number")
Warning: Use of `pca_df[[paste0("PC", substr(pca, start = 3, stop = 3))]]` is discouraged.
ℹ Use `.data[[paste0("PC", substr(pca, start = 3, stop = 3))]]` instead.
Warning: Use of `pca_df[[paste0("PC", substr(pcb, start = 3, stop = 3))]]` is discouraged.
ℹ Use `.data[[paste0("PC", substr(pcb, start = 3, stop = 3))]]` instead.
Warning: Use of `pca_df[[colors]]` is discouraged.
ℹ Use `.data[[colors]]` instead.
Warning: Use of `pca_df[[shapes]]` is discouraged.
ℹ Use `.data[[shapes]]` instead.
Warning: Use of `pca_df[[text_column]]` is discouraged.
ℹ Use `.data[[text_column]]` instead.
Warning: Use of `pca_df[[paste0("PC", substr(pca, start = 3, stop = 3))]]` is discouraged.
ℹ Use `.data[[paste0("PC", substr(pca, start = 3, stop = 3))]]` instead.
Warning: Use of `pca_df[[paste0("PC", substr(pcb, start = 3, stop = 3))]]` is discouraged.
ℹ Use `.data[[paste0("PC", substr(pcb, start = 3, stop = 3))]]` instead.
Warning: Use of `pca_df[[shapes]]` is discouraged.
ℹ Use `.data[[shapes]]` instead.

m_pca_tibia_t <- run_pca_structuring(matrix_data = matrix_counts_tibia,transpose = TRUE,filter_empty_samples_counts = 30)
m_pca_hip_t <- run_pca_structuring(matrix_data = matrix_counts_hip,transpose = TRUE,filter_empty_samples_counts = 30)

Tibia

### Need to be run the run_pca_structuring before the plot the pca otherwise the objects mess up
# Generate the columns in the md_df
plot_the_pca(pca_df = m_pca_tibia_t$matrix_pca,
             percentVar_obj = m_pca_tibia_t$percentVar_obj,
             colors =  "tissue_celltype_lowercase",shapes = "health_status",
             pca = "PC1",pcb = "PC2",
             title="PCA of RNA-seq Raw Data",subtitle = "Tibias SVF and Adipocyte Transposed",
             text_column = "sample_number")
Warning: Use of `pca_df[[paste0("PC", substr(pca, start = 3, stop = 3))]]` is discouraged.
ℹ Use `.data[[paste0("PC", substr(pca, start = 3, stop = 3))]]` instead.
Warning: Use of `pca_df[[paste0("PC", substr(pcb, start = 3, stop = 3))]]` is discouraged.
ℹ Use `.data[[paste0("PC", substr(pcb, start = 3, stop = 3))]]` instead.
Warning: Use of `pca_df[[colors]]` is discouraged.
ℹ Use `.data[[colors]]` instead.
Warning: Use of `pca_df[[shapes]]` is discouraged.
ℹ Use `.data[[shapes]]` instead.
Warning: Use of `pca_df[[text_column]]` is discouraged.
ℹ Use `.data[[text_column]]` instead.
Warning: Use of `pca_df[[paste0("PC", substr(pca, start = 3, stop = 3))]]` is discouraged.
ℹ Use `.data[[paste0("PC", substr(pca, start = 3, stop = 3))]]` instead.
Warning: Use of `pca_df[[paste0("PC", substr(pcb, start = 3, stop = 3))]]` is discouraged.
ℹ Use `.data[[paste0("PC", substr(pcb, start = 3, stop = 3))]]` instead.
Warning: Use of `pca_df[[shapes]]` is discouraged.
ℹ Use `.data[[shapes]]` instead.

Hip

### Need to be run the run_pca_structuring before the plot the pca otherwise the objects mess up
# Generate the columns in the md_df
plot_the_pca(pca_df = m_pca_hip_t$matrix_pca,
             percentVar_obj = m_pca_hip_t$percentVar_obj,
             colors =  "tissue_celltype_lowercase",shapes = "health_status",
             pca = "PC1",pcb = "PC2",
             title="PCA of RNA-seq Raw Data",
             subtitle = "Hips SVF and Adipocyte Transposed",
             text_column = "sample_number")
Warning: Use of `pca_df[[paste0("PC", substr(pca, start = 3, stop = 3))]]` is discouraged.
ℹ Use `.data[[paste0("PC", substr(pca, start = 3, stop = 3))]]` instead.
Warning: Use of `pca_df[[paste0("PC", substr(pcb, start = 3, stop = 3))]]` is discouraged.
ℹ Use `.data[[paste0("PC", substr(pcb, start = 3, stop = 3))]]` instead.
Warning: Use of `pca_df[[colors]]` is discouraged.
ℹ Use `.data[[colors]]` instead.
Warning: Use of `pca_df[[shapes]]` is discouraged.
ℹ Use `.data[[shapes]]` instead.
Warning: Use of `pca_df[[text_column]]` is discouraged.
ℹ Use `.data[[text_column]]` instead.
Warning: Use of `pca_df[[paste0("PC", substr(pca, start = 3, stop = 3))]]` is discouraged.
ℹ Use `.data[[paste0("PC", substr(pca, start = 3, stop = 3))]]` instead.
Warning: Use of `pca_df[[paste0("PC", substr(pcb, start = 3, stop = 3))]]` is discouraged.
ℹ Use `.data[[paste0("PC", substr(pcb, start = 3, stop = 3))]]` instead.
Warning: Use of `pca_df[[shapes]]` is discouraged.
ℹ Use `.data[[shapes]]` instead.

Tibia Adipocytes

m_pca_tibia_transposed_adipocytes <- run_pca_structuring(matrix_data = matrix_counts_tibia |> dplyr::select("Gene_id","Gene_name",ends_with("adipocyte")),transpose = TRUE,filter_empty_samples_counts = 30)

plot_the_pca(pca_df = m_pca_tibia_transposed_adipocytes$matrix_pca,
             percentVar_obj = m_pca_tibia_transposed_adipocytes$percentVar_obj,
             colors =  "tissue_celltype_lowercase",
             shapes = "health_status",
             pca = "PC1",pcb = "PC2",
             title="PCA of RNA-seq Raw Data",subtitle = "Tibias Adipocytes Transposed",
             text_column = "sample_number")
Warning: Use of `pca_df[[paste0("PC", substr(pca, start = 3, stop = 3))]]` is discouraged.
ℹ Use `.data[[paste0("PC", substr(pca, start = 3, stop = 3))]]` instead.
Warning: Use of `pca_df[[paste0("PC", substr(pcb, start = 3, stop = 3))]]` is discouraged.
ℹ Use `.data[[paste0("PC", substr(pcb, start = 3, stop = 3))]]` instead.
Warning: Use of `pca_df[[colors]]` is discouraged.
ℹ Use `.data[[colors]]` instead.
Warning: Use of `pca_df[[shapes]]` is discouraged.
ℹ Use `.data[[shapes]]` instead.
Warning: Use of `pca_df[[text_column]]` is discouraged.
ℹ Use `.data[[text_column]]` instead.
Warning: Use of `pca_df[[paste0("PC", substr(pca, start = 3, stop = 3))]]` is discouraged.
ℹ Use `.data[[paste0("PC", substr(pca, start = 3, stop = 3))]]` instead.
Warning: Use of `pca_df[[paste0("PC", substr(pcb, start = 3, stop = 3))]]` is discouraged.
ℹ Use `.data[[paste0("PC", substr(pcb, start = 3, stop = 3))]]` instead.
Warning: Use of `pca_df[[shapes]]` is discouraged.
ℹ Use `.data[[shapes]]` instead.

# Issued samples with low number of genes per sample from HTML report
#107 tibia non sclerotic adipocyte
#107 tibia sclerotic adipocyte
##99 tibia sclerotic adipocyte


#80 tibia non sclerotic pellet
#163 tibia sclerotic pellet

Tibia SVF/Pellet

m_pca_tibia_transposed_pellet <- run_pca_structuring(matrix_data = matrix_counts_tibia |> dplyr::select("Gene_id","Gene_name",ends_with("pellet")),transpose = TRUE,filter_empty_samples_counts = 30)


plot_the_pca(pca_df = m_pca_tibia_transposed_pellet$matrix_pca,
             percentVar_obj = m_pca_tibia_transposed_pellet$percentVar_obj,
             colors =  "tissue_celltype_lowercase",
             shapes = "health_status",
             pca = "PC1",pcb = "PC2",
             title="PCA of RNA-seq Raw Data",subtitle = "Tibias Pellet Transposed",
             text_column = "sample_number")
Warning: Use of `pca_df[[paste0("PC", substr(pca, start = 3, stop = 3))]]` is discouraged.
ℹ Use `.data[[paste0("PC", substr(pca, start = 3, stop = 3))]]` instead.
Warning: Use of `pca_df[[paste0("PC", substr(pcb, start = 3, stop = 3))]]` is discouraged.
ℹ Use `.data[[paste0("PC", substr(pcb, start = 3, stop = 3))]]` instead.
Warning: Use of `pca_df[[colors]]` is discouraged.
ℹ Use `.data[[colors]]` instead.
Warning: Use of `pca_df[[shapes]]` is discouraged.
ℹ Use `.data[[shapes]]` instead.
Warning: Use of `pca_df[[text_column]]` is discouraged.
ℹ Use `.data[[text_column]]` instead.
Warning: Use of `pca_df[[paste0("PC", substr(pca, start = 3, stop = 3))]]` is discouraged.
ℹ Use `.data[[paste0("PC", substr(pca, start = 3, stop = 3))]]` instead.
Warning: Use of `pca_df[[paste0("PC", substr(pcb, start = 3, stop = 3))]]` is discouraged.
ℹ Use `.data[[paste0("PC", substr(pcb, start = 3, stop = 3))]]` instead.
Warning: Use of `pca_df[[shapes]]` is discouraged.
ℹ Use `.data[[shapes]]` instead.

# Issued samples with low number of genes per sample from HTML report

#80 tibia non sclerotic pellet
#163 tibia sclerotic pellet

Hip Adipocytes

m_pca_hip_transposed_adipocytes <- run_pca_structuring(matrix_data = matrix_counts_hip |> dplyr::select("Gene_id","Gene_name",ends_with("adipocyte")),transpose = TRUE,filter_empty_samples_counts = 30)

plot_the_pca(pca_df = m_pca_hip_transposed_adipocytes$matrix_pca,
             percentVar_obj = m_pca_hip_transposed_adipocytes$percentVar_obj,
             colors =  "tissue_celltype_lowercase",
             shapes = "health_status",
             pca = "PC1",pcb = "PC2",
             title="PCA of RNA-seq Raw Data",subtitle = "Hips Adipocytes Transposed",
             text_column = "sample_number")
Warning: Use of `pca_df[[paste0("PC", substr(pca, start = 3, stop = 3))]]` is discouraged.
ℹ Use `.data[[paste0("PC", substr(pca, start = 3, stop = 3))]]` instead.
Warning: Use of `pca_df[[paste0("PC", substr(pcb, start = 3, stop = 3))]]` is discouraged.
ℹ Use `.data[[paste0("PC", substr(pcb, start = 3, stop = 3))]]` instead.
Warning: Use of `pca_df[[colors]]` is discouraged.
ℹ Use `.data[[colors]]` instead.
Warning: Use of `pca_df[[shapes]]` is discouraged.
ℹ Use `.data[[shapes]]` instead.
Warning: Use of `pca_df[[text_column]]` is discouraged.
ℹ Use `.data[[text_column]]` instead.
Warning: Use of `pca_df[[paste0("PC", substr(pca, start = 3, stop = 3))]]` is discouraged.
ℹ Use `.data[[paste0("PC", substr(pca, start = 3, stop = 3))]]` instead.
Warning: Use of `pca_df[[paste0("PC", substr(pcb, start = 3, stop = 3))]]` is discouraged.
ℹ Use `.data[[paste0("PC", substr(pcb, start = 3, stop = 3))]]` instead.
Warning: Use of `pca_df[[shapes]]` is discouraged.
ℹ Use `.data[[shapes]]` instead.

# Issued samples with low number of genes per sample from HTML report, expected to be also associated with low number of sequencing read per sample...
#74 hip non sclerotic adipocyte
#79 hip non sclerotic adipocyte
#150 hip non sclerotic adipocyte

#74 hip sclerotic adipocyte
#79 hip sclerotic adipocyte

#78 hip non sclerotic adipocyte
#78 hip sclerotic adipocyte

Hip SVF/Pellet

m_pca_hip_transposed_pellet <- run_pca_structuring(matrix_data = matrix_counts_hip |> dplyr::select("Gene_id","Gene_name",ends_with("pellet")),transpose = TRUE,filter_empty_samples_counts = 30)


plot_the_pca(pca_df = m_pca_hip_transposed_pellet$matrix_pca,
             percentVar_obj = m_pca_hip_transposed_pellet$percentVar_obj,
             colors =  "tissue_celltype_lowercase",
             shapes = "health_status",
             pca = "PC1",pcb = "PC2",
             title="PCA of RNA-seq Raw Data",subtitle = "Hips Pellet Transposed",
             text_column = "sample_number")
Warning: Use of `pca_df[[paste0("PC", substr(pca, start = 3, stop = 3))]]` is discouraged.
ℹ Use `.data[[paste0("PC", substr(pca, start = 3, stop = 3))]]` instead.
Warning: Use of `pca_df[[paste0("PC", substr(pcb, start = 3, stop = 3))]]` is discouraged.
ℹ Use `.data[[paste0("PC", substr(pcb, start = 3, stop = 3))]]` instead.
Warning: Use of `pca_df[[colors]]` is discouraged.
ℹ Use `.data[[colors]]` instead.
Warning: Use of `pca_df[[shapes]]` is discouraged.
ℹ Use `.data[[shapes]]` instead.
Warning: Use of `pca_df[[text_column]]` is discouraged.
ℹ Use `.data[[text_column]]` instead.
Warning: Use of `pca_df[[paste0("PC", substr(pca, start = 3, stop = 3))]]` is discouraged.
ℹ Use `.data[[paste0("PC", substr(pca, start = 3, stop = 3))]]` instead.
Warning: Use of `pca_df[[paste0("PC", substr(pcb, start = 3, stop = 3))]]` is discouraged.
ℹ Use `.data[[paste0("PC", substr(pcb, start = 3, stop = 3))]]` instead.
Warning: Use of `pca_df[[shapes]]` is discouraged.
ℹ Use `.data[[shapes]]` instead.

# Issued samples with low number of genes per sample from HTML report

 
#74 Hip non sclerotic pellet
#74 Hip sclerotic pellet
#78 hip non.sclerotic pellet
#78 hip sclerotic pellet
md_df
plot_the_pca(pca_df = m_pca_hip_transposed_pellet$matrix_pca,
             percentVar_obj = m_pca_hip_transposed_pellet$percentVar_obj,
             colors =  "tissue_celltype_lowercase",
             shapes = "health_status",
             pca = "PC1",pcb = "PC2",
             title="PCA of RNA-seq Raw Data",subtitle = "Hips Pellet Transposed",
             text_column = "Age")
Warning: Use of `pca_df[[paste0("PC", substr(pca, start = 3, stop = 3))]]` is discouraged.
ℹ Use `.data[[paste0("PC", substr(pca, start = 3, stop = 3))]]` instead.
Warning: Use of `pca_df[[paste0("PC", substr(pcb, start = 3, stop = 3))]]` is discouraged.
ℹ Use `.data[[paste0("PC", substr(pcb, start = 3, stop = 3))]]` instead.
Warning: Use of `pca_df[[colors]]` is discouraged.
ℹ Use `.data[[colors]]` instead.
Warning: Use of `pca_df[[shapes]]` is discouraged.
ℹ Use `.data[[shapes]]` instead.
Warning: Use of `pca_df[[text_column]]` is discouraged.
ℹ Use `.data[[text_column]]` instead.
Warning: Use of `pca_df[[paste0("PC", substr(pca, start = 3, stop = 3))]]` is discouraged.
ℹ Use `.data[[paste0("PC", substr(pca, start = 3, stop = 3))]]` instead.
Warning: Use of `pca_df[[paste0("PC", substr(pcb, start = 3, stop = 3))]]` is discouraged.
ℹ Use `.data[[paste0("PC", substr(pcb, start = 3, stop = 3))]]` instead.
Warning: Use of `pca_df[[shapes]]` is discouraged.
ℹ Use `.data[[shapes]]` instead.

plot_the_pca(pca_df = m_pca_hip_transposed_pellet$matrix_pca,
             percentVar_obj = m_pca_hip_transposed_pellet$percentVar_obj,
             colors =  "Gender",
             shapes = "health_status",
             pca = "PC1",pcb = "PC2",
             title="PCA of RNA-seq Raw Data",subtitle = "Hips Pellet Transposed",
             text_column = "Age")
Warning: Use of `pca_df[[paste0("PC", substr(pca, start = 3, stop = 3))]]` is discouraged.
ℹ Use `.data[[paste0("PC", substr(pca, start = 3, stop = 3))]]` instead.
Warning: Use of `pca_df[[paste0("PC", substr(pcb, start = 3, stop = 3))]]` is discouraged.
ℹ Use `.data[[paste0("PC", substr(pcb, start = 3, stop = 3))]]` instead.
Warning: Use of `pca_df[[colors]]` is discouraged.
ℹ Use `.data[[colors]]` instead.
Warning: Use of `pca_df[[shapes]]` is discouraged.
ℹ Use `.data[[shapes]]` instead.
Warning: Use of `pca_df[[text_column]]` is discouraged.
ℹ Use `.data[[text_column]]` instead.
Warning: Use of `pca_df[[paste0("PC", substr(pca, start = 3, stop = 3))]]` is discouraged.
ℹ Use `.data[[paste0("PC", substr(pca, start = 3, stop = 3))]]` instead.
Warning: Use of `pca_df[[paste0("PC", substr(pcb, start = 3, stop = 3))]]` is discouraged.
ℹ Use `.data[[paste0("PC", substr(pcb, start = 3, stop = 3))]]` instead.
Warning: Use of `pca_df[[shapes]]` is discouraged.
ℹ Use `.data[[shapes]]` instead.

Test of QC for samples

Remove if are away for complexity or number of genes.

m_pca_tibia$matrix_raw

Plot the number of reads per sample from raw matrix of tibia.

#matrix_counts_tibia
#m_pca_tibia$matrix_raw

sums_mm = colSums(m_pca_tibia$matrix_raw[3:ncol(m_pca_tibia$matrix_raw)])
sums_mm <- data.frame(Column = colnames(m_pca_tibia$matrix_raw[3:ncol(m_pca_tibia$matrix_raw)]), Sum = sums_mm)
sums_mm$Column <-tolower(sums_mm$Column)



# Categorize the groups based on the Column names
sums_mm$Group <- ifelse(grepl("tibia_non.sclerotic_adipocyte", sums_mm$Column), "TNSA",
                   ifelse(grepl("tibia_sclerotic_adipocyte", sums_mm$Column), "TSA",
                          ifelse(grepl("tibia_non.sclerotic_pellet", sums_mm$Column), "TNSP", "TSP")))

sums_mm
# Create a custom color palette
color_palette <- c("TNSA" = "#00296b", "TSA" = "#1e91d0", "TNSP" = "#faa819","TSP"="#f37520")
library(ggplot2)
mean_sum <- mean(sums_mm$Sum)
quantiles <- quantile(sums_mm$Sum, probs = c(0.25, 0.75,0.90))

p <- ggplot(sums_mm, aes(x = reorder(Column, Sum), y = Sum, fill = Group)) +
#ggplot(sums_mm, aes(x = Column, y = Sum, fill = Group)) +
  

  geom_bar(stat = "identity") +
  labs(title = "Counts Sums",
       x = "Samples",
       y = "Sum of all counts") +
  scale_fill_manual(values = color_palette) +
  geom_hline(aes(yintercept = mean_sum, color = "Mean"), linetype = "dashed", size = 1) +
  geom_hline(aes(yintercept = quantiles[1], color = "25th Percentile"), linetype = "dotted", size = 1) +
  geom_hline(aes(yintercept = quantiles[2], color = "75th Percentile"), linetype = "dotted", size = 1) +
  geom_hline(aes(yintercept = quantiles[3], color = "90th Percentile"), linetype = "dotted", size = 1) +
  scale_color_manual(values = c("red", "blue", "green","#903498"),
                     breaks = c("Mean", "25th Percentile", "75th Percentile", "90th Percentile"),
                     name = "Statistics") +  theme(axis.text.x = element_text(angle = 90, hjust = 1),
        axis.text.y = element_text(size = 12),
        panel.background = element_blank(),  # Remove panel background
        panel.grid.major = element_blank(),  # Remove major grid lines
        panel.grid.minor = element_blank(),  # Remove minor grid lines
        )  # Rotate x-axis labels for better visibility

plotly::ggplotly(p)

TIBIA Samples out

#X163 TSP #X99 TSA #X107 TNSA TSA TNSP #X80 TNSP TNSA TSP #X105 TSP TNSP #X148 TSP #X104 TSA TSP #X164 TSA #X109 TNSP # we filter out around same proportions if 25% in TIBIA is around 700k we filtered 407265 and in HIP 25% is 1M in Hip, we filterd 791K

sums_mm |> dplyr::filter(Sum < 407265)
sums_mm_tibia <- sums_mm |> dplyr::filter(!Sum < 407265)

HIP

m_pca_hip$matrix_raw

Plot the number of reads per sample from raw matrix of tibia.

#matrix_counts_hip
#m_pca_hip$matrix_raw
sums_mm = colSums(m_pca_hip$matrix_raw[3:ncol(m_pca_hip$matrix_raw)])
sums_mm <- data.frame(Column = colnames(m_pca_hip$matrix_raw[3:ncol(m_pca_hip$matrix_raw)]), Sum = sums_mm)


sums_mm$Column <-tolower(sums_mm$Column)


# Categorize the groups based on the Column names
sums_mm$Group <- ifelse(grepl("hip_non.sclerotic_adipocyte", sums_mm$Column), "HNSA",
                   ifelse(grepl("hip_sclerotic_adipocyte", sums_mm$Column), "HSA",
                          ifelse(grepl("hip_non.sclerotic_pellet", sums_mm$Column), "HNSP", "HSP")))

sums_mm
# Create a custom color palette
color_palette <- c("HNSA" = "#00296b", "HSA" = "#1e91d0", "HNSP" = "#faa819","HSP"="#f37520")
library(ggplot2)
c <- mean(sums_mm$Sum)
quantiles <- quantile(sums_mm$Sum, probs = c(0.25, 0.75,0.90))

p <- ggplot(sums_mm, aes(x = reorder(Column, Sum), y = Sum, fill = Group)) +
#ggplot(sums_mm, aes(x = Column, y = Sum, fill = Group)) +
  

  geom_bar(stat = "identity") +
  labs(title = "Counts Sums",
       x = "Samples",
       y = "Sum of all counts") +
  scale_fill_manual(values = color_palette) +
  geom_hline(aes(yintercept = mean_sum, color = "Mean"), linetype = "dashed", size = 1) +
  geom_hline(aes(yintercept = quantiles[1], color = "25th Percentile"), linetype = "dotted", size = 1) +
  geom_hline(aes(yintercept = quantiles[2], color = "75th Percentile"), linetype = "dotted", size = 1) +
  geom_hline(aes(yintercept = quantiles[3], color = "90th Percentile"), linetype = "dotted", size = 1) +
  scale_color_manual(values = c("red", "blue", "green","#903498"),
                     breaks = c("Mean", "25th Percentile", "75th Percentile", "90th Percentile"),
                     name = "Statistics") +  theme(axis.text.x = element_text(angle = 90, hjust = 1),
        axis.text.y = element_text(size = 12),
        panel.background = element_blank(),  # Remove panel background
        panel.grid.major = element_blank(),  # Remove major grid lines
        panel.grid.minor = element_blank(),  # Remove minor grid lines
        )  # Rotate x-axis labels for better visibility

plotly::ggplotly(p)

HIP Samples out

#####X78 - 4 #####X74 -4 #####X79 -2 HNSA and HSA #####X150 HNSA #####X154 HNSP # Removed all the samples with less than 791286 counts in Hip.

Filter Samples

sums_mm_hip <- sums_mm |> dplyr::filter(!Sum < 791286)
sums_mm |> dplyr::filter(Sum < 791286)
sums_mm_hip
NA

Differential gene expression.

Separate the data in smaller groups.

#tibia

#hip

#adipo

#pellet

#sclerotic

#non_sclerotic
# 
# tibias-> sclerotic vs nsclerotic
# hip-> sclerotic vs nsclerotic
# 
# Adipocyte -> tibia vs Hip
# 
# 
# Adipocytes
# Non-sclerotic vs Sclerotic of Hip
# Non-sclerotic vs Sclerotic of Tibia
# Non-sclerotic Tibia vs Non-sclerotic Hip
# Sclerotic Tibia vs Sclerotic Hip
# 
# 
# Pellet
# Non-sclerotic vs Sclerotic of Hip
# Non-sclerotic vs Sclerotic of Tibia
# Non-sclerotic Tibia vs Non-sclerotic Hip
# Sclerotic Tibia vs Sclerotic Hip
# 
# Adipocytes vs Pellet results --> Venn 
# Non sclerotic alone
# Sclerotic alone

Comparisons

Use the samples cleaned objects

sums_mm_tibia sums_mm_hip

filter out the samples we removed before


sums_mm_tibia
sums_mm_hip
#matrix_counts_tibia
#matrix_counts_hip

m_pca_tibia$matrix_raw_filtered_samples_for_DEG <- m_pca_tibia$matrix_raw[,rownames(sums_mm_tibia)]
m_pca_hip$matrix_raw_filtered_samples_for_DEG <- m_pca_hip$matrix_raw[,rownames(sums_mm_hip)]
#using dplyr
#m_pca_tibia$matrix_raw_filtered_samples_for_DEG <- m_pca_tibia$matrix_raw |>   select(all_of(rownames(sums_mm_tibia)))

EDGER

LRT: Suitable for complex designs but may not fully account for variability, potentially leading to inflated false positives.

QLF: Provides robust results by modeling extra variability through quasi-likelihood methods and shrinkage estimators. It yields more accurate p-values and better control over false positives.

— Normalize

LS0tCnRpdGxlOiAiTGVhIEhpcCAmIFRpYmlhIEJSQnNlcSBKdWx5IDIwMjQgIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgpgYGB7cn0Kc2V0d2QoIi9ob21lL21ib3Rvcy9DTFVTVEVSL0Vudmlyb25tZW50cy8yMDI0XzA3XzA1X0xlYV9MYXVzYW5uZV9IaXBfVGliaWFfQlJCc2VxLyIpCmBgYApQYXRoIHRvIHRoZSBkYXRhOiAqKipFbnZpcm9ubWVudHMvMjAyNF8wN18wNV9MZWFfTGF1c2FubmVfSGlwX1RpYmlhX0JSQnNlcSoqKgoKCiMgLS0tIEltcG9ydCBsaWJyYXJpZXMKYGBge3J9CiNsaWJyYXJ5KEJpb2NNYW5hZ2VyKQpybShsaXN0ID0gbHMoYWxsLm5hbWVzID0gVFJVRSkpCmdjKCkKLmxpYlBhdGhzKCIvaG9tZS9tYm90b3MvUi94ODZfNjQtcGMtbGludXgtZ251LWxpYnJhcnkvNC4yLyIpCiMgQmlvY01hbmFnZXI6Omluc3RhbGwoYygiZG9yb3RoZWEiKSxmb3JjZT1UUlVFLGFzayA9IFRSVUUpCiMgbGlicmFyeShkb3JvdGhlYSkKCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkodGlkeXIpCmxpYnJhcnkoZWRnZVIpCmBgYAoKCgojIC0tLSBSZWFkIHRhYmxlcwpgYGB7cn0KbWF0cml4X2NvdW50c190aWJpYSA8LSByZWFkLnRhYmxlKGZpbGUgPSIvaG9tZS9tYm90b3MvQ0xVU1RFUi9FbnZpcm9ubWVudHMvMjAyNF8wN18wNV9MZWFfTGF1c2FubmVfSGlwX1RpYmlhX0JSQnNlcS9icmJzZXEtbmYtcGlwZWxpbmUvcmVzdWx0cy9BTVAwMjExL2NvdW50X21hdHJpeC9MMjcwNTI0TEYwMV8wMS5yZWFkLmNvdW50cy5zYW1wbGVJRHMuZGV0YWlsZWQudHh0IixzZXAgPSAiXHQiLGhlYWRlciA9IFRSVUUpCmhlYWQobWF0cml4X2NvdW50c190aWJpYSkKdGFpbChtYXRyaXhfY291bnRzX3RpYmlhKQpkaW0obWF0cml4X2NvdW50c190aWJpYSkKbWF0cml4X2NvdW50c190aWJpYQpgYGAKYGBge3J9Cm1hdHJpeF9jb3VudHNfaGlwIDwtIHJlYWQudGFibGUoZmlsZSA9Ii9ob21lL21ib3Rvcy9DTFVTVEVSL0Vudmlyb25tZW50cy8yMDI0XzA3XzA1X0xlYV9MYXVzYW5uZV9IaXBfVGliaWFfQlJCc2VxL2JyYnNlcS1uZi1waXBlbGluZS9yZXN1bHRzL0FNUDAyMTEvY291bnRfbWF0cml4L0wyNzA1MjRMRjAyXzAxLnJlYWQuY291bnRzLnNhbXBsZUlEcy5kZXRhaWxlZC50eHQiLHNlcCA9ICJcdCIsaGVhZGVyID0gVFJVRSkKaGVhZChtYXRyaXhfY291bnRzX2hpcCkKdGFpbChtYXRyaXhfY291bnRzX2hpcCkKZGltKG1hdHJpeF9jb3VudHNfaGlwKQptYXRyaXhfY291bnRzX2hpcApgYGAKCgpgYGB7cn0KbmNvbChtYXRyaXhfY291bnRzX3RpYmlhKQpjb2xuYW1lcyhtYXRyaXhfY291bnRzX3RpYmlhKQpgYGAKCmBgYHtyfQpuY29sKG1hdHJpeF9jb3VudHNfaGlwKQpjb2xuYW1lcyhtYXRyaXhfY291bnRzX2hpcCkKYGBgCgoKYGBge3J9CiMgUmVtb3ZlIHRoZSBsYXN0IGNvbHVtbgojIE5ldyB2ZXJzaW9uIGRvIG5vdCBuZWVkIHRvIGJlIHJlbW92ZWQsIFVrbm93biBjb2x1bW5zIGlzIG5vdCB0aGVyZSBhbnltb3JlLi4uCiN0aGUgR2VuZV9pZCBvciBHZW5lX25hbWUgd2hpY2ggYXJlIGluIHRoZSBwb3NpdGlvbiAxIGFuZCAyCgojbWF0cml4X2NvdW50cyA8LSBtYXRyaXhfY291bnRzWywtbmNvbChtYXRyaXhfY291bnRzKV0KCiMgUmVtb3ZlIHRoZSBsYXN0IDUgcm93cwptYXRyaXhfY291bnRzX3RpYmlhIDwtIG1hdHJpeF9jb3VudHNfdGliaWFbMToobnJvdyhtYXRyaXhfY291bnRzX3RpYmlhKS01KSxdCmhlYWQobWF0cml4X2NvdW50c190aWJpYSkKdGFpbChtYXRyaXhfY291bnRzX3RpYmlhKQpkaW0obWF0cml4X2NvdW50c190aWJpYSkKY29sbmFtZXMobWF0cml4X2NvdW50c190aWJpYSlbMzpuY29sKG1hdHJpeF9jb3VudHNfdGliaWEpXQpgYGAKYGBge3J9CiMgUmVtb3ZlIHRoZSBsYXN0IDUgcm93cwptYXRyaXhfY291bnRzX2hpcCA8LSBtYXRyaXhfY291bnRzX2hpcFsxOihucm93KG1hdHJpeF9jb3VudHNfaGlwKS01KSxdCmhlYWQobWF0cml4X2NvdW50c19oaXApCnRhaWwobWF0cml4X2NvdW50c19oaXApCmRpbShtYXRyaXhfY291bnRzX2hpcCkKY29sbmFtZXMobWF0cml4X2NvdW50c19oaXApWzM6bmNvbChtYXRyaXhfY291bnRzX2hpcCldCmBgYAoKCgoKIyBNYXliZSBsYXRlciB3ZSBuZWVkIHRvIGRpdmlkZSBpdCBpbnRvIEFkaXBvLFBlbGxldCBmcm9tIFRpYmlhcyBhbmQgSGlwcwpgYGB7cn0KIyB3cm9uZ19uYW1lcyA8LSBjKCJtSEgzLjEyUDE1Li4uRjNuZWciLCJtSEgzLjEyUDI4LkVXLi4uRjNuZWciLCJtSEgzLjEyUDI4LkN0cmwuLi5GM25lZyIpCiMgY29sbmFtZXMobWF0cml4X2NvdW50cylbMzoxMDRdIDwtIGdzdWIoeCA9IGNvbG5hbWVzKG1hdHJpeF9jb3VudHMpWzM6MTA0XSxwYXR0ZXJuID0gIkYzLiQiLHJlcGxhY2VtZW50ID0gIkYzKyIpCiMgZm9yICh3cm9uZ19uYW1lIGluIHdyb25nX25hbWVzKXsKIyAgIGNvcnJlY3RfbmFtZSA8LSBnc3ViKHBhdHRlcm4gPSAiUCIscmVwbGFjZW1lbnQgPSAiLlAiLHggPSB3cm9uZ19uYW1lKQojICAgY29sbmFtZXMobWF0cml4X2NvdW50cylbY29sbmFtZXMobWF0cml4X2NvdW50cykgPT0gd3JvbmdfbmFtZV0gPC0gY29ycmVjdF9uYW1lCiMgfQojIAojIAojIG1hdHJpeF9hc3BjcyA8LSBtYXRyaXhfY291bnRzWzM6bmNvbChtYXRyaXhfY291bnRzKV0gfD4gZHBseXI6OnNlbGVjdChtYXRjaGVzKCJBU1BDcyIpKQojIG1hdHJpeF9mM3BvcyA8LSBtYXRyaXhfY291bnRzWzM6bmNvbChtYXRyaXhfY291bnRzKV0gfD4gZHBseXI6OnNlbGVjdChlbmRzX3dpdGgoIkYzKyIsKSkKIyBtYXRyaXhfZjNuZWcgPC0gbWF0cml4X2NvdW50c1szOm5jb2wobWF0cml4X2NvdW50cyldIHw+IGRwbHlyOjpzZWxlY3QoZW5kc193aXRoKCJGM25lZyIpKQoKYGBgCgojIC0tLSBBZGQgbWV0YWRhdGEgdGFibGUgZnJvbSB0aGUgeGxzeCBmaWxlCmBgYHtyfQptZCA8LSByZWFkeGw6OnJlYWRfeGxzeChwYXRoID0iL2hvbWUvbWJvdG9zL0NMVVNURVIvRW52aXJvbm1lbnRzLzIwMjRfMDdfMDVfTGVhX0xhdXNhbm5lX0hpcF9UaWJpYV9CUkJzZXEvQW5hbHlzaXMvbWV0YWRhdGEvc2FtcGxlX2luZm9fbWluaW1hbF9TSVQueGxzeCIpCm1kJHNhbXBsZUlECmBgYAoKYGBge3J9CgojIFVzZSBtdXRhdGUgdG8gZm9ybWF0IHRoZSBzYW1wbGUgSURzCm1kX2RmIDwtIG1kICU+JSAKICBkcGx5cjo6bXV0YXRlKHNhbXBsZUlEID0gZ3N1YigiICIsICIuIiwgc2FtcGxlSUQpKSAlPiUKICBkcGx5cjo6bXV0YXRlKHNhbXBsZUlEID0gcGFzdGUwKCJYIiwgc2FtcGxlSUQpKQoKIyBEaXNwbGF5IHRoZSBkYXRhIGZyYW1lIHdpdGggZm9ybWF0dGVkIHNhbXBsZSBJRHMKcHJpbnQobWRfZGYpCmBgYAoKCgpgYGB7cn0KbWQKbWRfZGYKCmBgYAoKCiMgR2VuZXJhdGUgbW9yZSBjb2x1bW5zIGZvciB0aGUgZGF0YSB0byBwbG90CmBgYHtyfQptZF9kZiRzYW1wbGVJRAojIFNwbGl0IHRoZSBzYW1wbGVJRCBjb2x1bW4KbWRfZGZfc3BsaXQgPC0gc3Ryc3BsaXQoYXMuY2hhcmFjdGVyKG1kX2RmJHNhbXBsZUlEKSwgIl8iLCBmaXhlZCA9IFRSVUUpCgojIENyZWF0ZSBuZXcgY29sdW1ucwptZF9kZiRzYW1wbGVfbnVtYmVyIDwtIHNhcHBseShtZF9kZl9zcGxpdCwgZnVuY3Rpb24oeCkgeFsxXSkKbWRfZGYkdGlzc3VlIDwtIHNhcHBseShtZF9kZl9zcGxpdCwgZnVuY3Rpb24oeCkgeFsyXSkKI21kX2RmJGhlYWx0aF9zdGF0dXMgPC0gc2FwcGx5KG1kX2RmX3NwbGl0LCBmdW5jdGlvbih4KSBwYXN0ZSh4WzNdLCB4WzRdLCBzZXAgPSAiXyIpKQptZF9kZiRoZWFsdGhfc3RhdHVzIDwtIHNhcHBseShtZF9kZl9zcGxpdCwgZnVuY3Rpb24oeCkgcGFzdGUoeFszXSwgc2VwID0gIl8iKSkKbWRfZGYkdGlzc3VlX2NlbGx0eXBlIDwtIHNhcHBseShtZF9kZl9zcGxpdCwgZnVuY3Rpb24oeCkgcGFzdGUoeFs0XSwgc2VwID0gIl8iKSkKbWRfZGYkdGlzc3VlX2NlbGx0eXBlX2xvd2VyY2FzZSA8LSB0b2xvd2VyKG1kX2RmJHRpc3N1ZV9jZWxsdHlwZSkKbWRfZGYkdGlzc3VlX2xvd2VyY2FzZSA8LSB0b2xvd2VyKG1kX2RmJHRpc3N1ZSkKbWRfZGYkZnVsbF9uYW1lIDwtIG1kX2RmJHNhbXBsZUlECgoKIyBWaWV3IHRoZSBkYXRhZnJhbWUKbWRfZGYKCmBgYAoKIyBBZGQgZ2VuZGVyLCBhZ2UgYW5kIEJNSSB0byBtZXRhZGF0YS4KYGBge3J9CmFnYm1pX2RmIDwtIHJlYWR4bDo6cmVhZF94bHN4KHBhdGggPSIvaG9tZS9tYm90b3MvQ0xVU1RFUi9FbnZpcm9ubWVudHMvMjAyNF8wN18wNV9MZWFfTGF1c2FubmVfSGlwX1RpYmlhX0JSQnNlcS9BbmFseXNpcy9tZXRhZGF0YS9hZ2UtZ2VuZGVyLUJSQnNlcS54bHN4IikKYWdibWlfZGYKCiMgQWRkIFggaW5mcm9udCBvZiB0aGUgc2FtcGxlIElEIGFuZCBjbG9zZSBub24gc2NsZXJvdGljIHdpdGggbm9uLnNjbGVyb3RpYy4KCmFnYm1pX2RmIDwtIGFnYm1pX2RmIHw+ICAKICBkcGx5cjo6bXV0YXRlKGBTYW1wbGUgSURgID0gZ3N1YigiICIsICIuIiwgYFNhbXBsZSBJRGApKSB8PiAKICBkcGx5cjo6bXV0YXRlKGBTYW1wbGUgSURgID0gcGFzdGUwKCJYIiwgYFNhbXBsZSBJRGApKQphZ2JtaV9kZgoKbWRfZGYgPC0gbWVyZ2UoeCA9IG1kX2RmLHkgPSBhZ2JtaV9kZixieS54ID0gInNhbXBsZUlEIixieS55ID0gIlNhbXBsZSBJRCIpCgpgYGAKCgoKCgoKCiMgT3JpZW50YXRpb24gb2YgRGF0YQojIyBUcmFuc3Bvc2VkIERhdGEgKHNhbXBsZXMgYXMgcm93cywgZ2VuZXMgYXMgY29sdW1ucykKCm0gPC0gcHJjb21wKHQobWF0cml4X2NvdW50c19oaXBbLDM6bmNvbChtYXRyaXhfY291bnRzX2hpcCldKSwgc2NhbGUuID0gVFJVRSwgY2VudGVyID0gVFJVRSkKSW5wdXQgTWF0cml4OiBBZnRlciB0cmFuc3Bvc2luZywgZWFjaCByb3cgcmVwcmVzZW50cyBhIHNhbXBsZSwgYW5kIGVhY2ggY29sdW1uIHJlcHJlc2VudHMgYSBnZW5lLgpJbnRlcnByZXRhdGlvbjogUENBIHdpbGwgaWRlbnRpZnkgcHJpbmNpcGFsIGNvbXBvbmVudHMgYmFzZWQgb24gdGhlIHZhcmlhbmNlIGFtb25nIHNhbXBsZXMgYWNyb3NzIGRpZmZlcmVudCBnZW5lcy4KUmVzdWx0czogVGhlIHByaW5jaXBhbCBjb21wb25lbnRzIHdpbGwgZGVzY3JpYmUgdGhlIHZhcmlhdGlvbiBiZXR3ZWVuIHRoZSBzYW1wbGVzLiBFYWNoIHByaW5jaXBhbCBjb21wb25lbnQgKFBDKSBpcyBhIGxpbmVhciBjb21iaW5hdGlvbiBvZiB0aGUgZ2VuZSBleHByZXNzaW9uIHZhbHVlcy4KCgojIyBOb24tVHJhbnNwb3NlZCBEYXRhIChnZW5lcyBhcyByb3dzLCBzYW1wbGVzIGFzIGNvbHVtbnMpCgptIDwtIHByY29tcChtYXRyaXhfY291bnRzX2hpcFssMzpuY29sKG1hdHJpeF9jb3VudHNfaGlwKV0sIHNjYWxlLiA9IFRSVUUsIGNlbnRlciA9IFRSVUUpCklucHV0IE1hdHJpeDogV2l0aG91dCB0cmFuc3Bvc2luZywgZWFjaCByb3cgcmVwcmVzZW50cyBhIGdlbmUsIGFuZCBlYWNoIGNvbHVtbiByZXByZXNlbnRzIGEgc2FtcGxlLgpJbnRlcnByZXRhdGlvbjogUENBIHdpbGwgaWRlbnRpZnkgcHJpbmNpcGFsIGNvbXBvbmVudHMgYmFzZWQgb24gdGhlIHZhcmlhbmNlIGFtb25nIGdlbmVzIGFjcm9zcyBkaWZmZXJlbnQgc2FtcGxlcy4KUmVzdWx0czogVGhlIHByaW5jaXBhbCBjb21wb25lbnRzIHdpbGwgZGVzY3JpYmUgdGhlIHZhcmlhdGlvbiBiZXR3ZWVuIHRoZSBnZW5lcy4gRWFjaCBwcmluY2lwYWwgY29tcG9uZW50IChQQykgaXMgYSBsaW5lYXIgY29tYmluYXRpb24gb2YgdGhlIHNhbXBsZSB2YWx1ZXMuCgoKIyBDaG9vc2luZyB0aGUgUmlnaHQgQXBwcm9hY2gKVGhlIGNob2ljZSBvZiB3aGV0aGVyIHRvIHRyYW5zcG9zZSB0aGUgZGF0YSBvciBub3QgZGVwZW5kcyBvbiB3aGF0IHlvdSB3YW50IHRvIGFuYWx5emU6CgojIyBBbmFseXppbmcgVmFyaWF0aW9uIEJldHdlZW4gU2FtcGxlczogSWYgeW91ciBnb2FsIGlzIHRvIGFuYWx5emUgaG93IHNhbXBsZXMgKGNvbmRpdGlvbnMpIHZhcnkgYmFzZWQgb24gZ2VuZSBleHByZXNzaW9uIHByb2ZpbGVzLCB5b3Ugc2hvdWxkIHRyYW5zcG9zZSB0aGUgZGF0YSBzbyB0aGF0IGVhY2ggcm93IHJlcHJlc2VudHMgYSBzYW1wbGUuIFRoaXMgd2lsbCBwcm92aWRlIHByaW5jaXBhbCBjb21wb25lbnRzIHRoYXQgZGVzY3JpYmUgdGhlIGRpZmZlcmVuY2VzIGJldHdlZW4gc2FtcGxlcy4KbSA8LSBwcmNvbXAodChtYXRyaXhfY291bnRzX2hpcFssMzpuY29sKG1hdHJpeF9jb3VudHNfaGlwKV0pLCBzY2FsZS4gPSBUUlVFLCBjZW50ZXIgPSBUUlVFKQoKCiMjIEFuYWx5emluZyBWYXJpYXRpb24gQmV0d2VlbiBHZW5lczogSWYgeW91ciBnb2FsIGlzIHRvIGFuYWx5emUgaG93IGdlbmVzIHZhcnkgYWNyb3NzIGRpZmZlcmVudCBzYW1wbGVzLCB5b3Ugc2hvdWxkIG5vdCB0cmFuc3Bvc2UgdGhlIGRhdGEsIGtlZXBpbmcgZ2VuZXMgYXMgcm93cyBhbmQgc2FtcGxlcyBhcyBjb2x1bW5zLiBUaGlzIHdpbGwgcHJvdmlkZSBwcmluY2lwYWwgY29tcG9uZW50cyB0aGF0IGRlc2NyaWJlIHRoZSBkaWZmZXJlbmNlcyBiZXR3ZWVuIGdlbmVzLgptIDwtIHByY29tcChtYXRyaXhfY291bnRzX2hpcFssMzpuY29sKG1hdHJpeF9jb3VudHNfaGlwKV0sIHNjYWxlLiA9IFRSVUUsIGNlbnRlciA9IFRSVUUpCgoKCiMgQ2xlYW4gcm93cyB0aGF0IGhhdmUgZ2VuZSBleHByZXNzaW9uIGZvciBhbGwgdGhlIHNhbXBsZXMgPCAzIGNvdW50cy4KYGBge3J9CiMgSWYgbm8gcmVzdWx0cyBvZiBERUcgb2J0YWluZWQsIHdlIHJlZHVjZSBzdHJpbmdlbmN5LCBzbyBsb3dlciB0aGUgbnVtYmVyLgoKbmNvbChtYXRyaXhfY291bnRzX2hpcCkKZGltKG1hdHJpeF9jb3VudHNfaGlwWywzOm5jb2wobWF0cml4X2NvdW50c19oaXApXVtyb3dTdW1zKG1hdHJpeF9jb3VudHNfaGlwWywzOm5jb2wobWF0cml4X2NvdW50c19oaXApXSkgPj0gMzAsXSkKZGltKG1hdHJpeF9jb3VudHNfdGliaWFbLDM6bmNvbChtYXRyaXhfY291bnRzX3RpYmlhKV1bcm93U3VtcyhtYXRyaXhfY291bnRzX3RpYmlhWywzOm5jb2wobWF0cml4X2NvdW50c190aWJpYSldKSA+PSAzMCxdKQoKYGBgCgoKYGBge3J9CiMgcm93X3N1bXMgPC0gcm93U3VtcyhtYXRyaXhfY291bnRzX2hpcFssIDM6bmNvbChtYXRyaXhfY291bnRzX2hpcCldKQojIG1hdHJpeF9jb3VudHNfaGlwX2ZpbHRlcmVkIDwtIG1hdHJpeF9jb3VudHNfaGlwW3Jvd19zdW1zID49IDMwLF0KIyBtYXRyaXhfY291bnRzX2hpcF9maWx0ZXJlZApgYGAKCgoKCiNGdW5jdGlvbiBmb3IgUENBLCByZW1vdmluZyBlbXB0eSBnZW5lcyBjb3VudHMgYW5kIGVtcHR5IGNvbHVtbnMgaWYgdHJuYXNwb3NlZC4KYGBge3J9CnJ1bl9wY2Ffc3RydWN0dXJpbmcgPC0gZnVuY3Rpb24obWF0cml4X2RhdGEsIHRyYW5zcG9zZT1UUlVFLGZpbHRlcl9lbXB0eV9zYW1wbGVzX2NvdW50cz0zMCl7CiAgCiAgZGF0YV9tYXRyaXhfcmF3IDwtIG1hdHJpeF9kYXRhCiAgZGF0YV9tYXRyaXggPC0gbWF0cml4X2RhdGFbLDM6bmNvbChtYXRyaXhfZGF0YSldCiAgcm93X3N1bXMgPSByb3dTdW1zKGRhdGFfbWF0cml4KQogIGRhdGFfbWF0cml4X2ZpbHRlcmVkID0gZGF0YV9tYXRyaXhbcm93X3N1bXMgPj0gZmlsdGVyX2VtcHR5X3NhbXBsZXNfY291bnRzLF0KICAKICAjIAogICMgIyBSZW1vdmUgY29uc3RhbnQvemVybyBjb2x1bW5zCiAgIyBub25fY29uc3RhbnRfY29sdW1ucyA8LSBhcHBseShkYXRhX21hdHJpeF9maWx0ZXJlZCwgMiwgZnVuY3Rpb24oeCkgc2QoeCkgIT0gMCkKICAjIGRhdGFfbWF0cml4X2ZpbHRlcmVkIDwtIGRhdGFfbWF0cml4X2ZpbHRlcmVkWywgbm9uX2NvbnN0YW50X2NvbHVtbnNdCgogICMgQ2hlY2sgdHJhbnNwb3NlCiAgaWYgKHRyYW5zcG9zZSl7CiAgICBkYXRhX21hdHJpeCA8LSB0KGRhdGFfbWF0cml4KQogIH0KICAKICAjUnVuIFBDQQogIAogIG0gPC0gcHJjb21wKGRhdGFfbWF0cml4X2ZpbHRlcmVkLHNjYWxlLiA9IFRSVUUsY2VudGVyID0gVFJVRSkKICAjY2FsY3VsYXQgdGhlIFBDICIlIidzCiAgcGVyY2VudFZhcl9vYmogPC0gbSRzZGV2XjIvc3VtKG0kc2Rldl4yKQogIAogICNTYXZlIGFzIGEgZGYKICBtIDwtIGFzLmRhdGEuZnJhbWUobVsyXSRyb3RhdGlvbikKICBtIDwtIG1lcmdlKHggPSBtLHkgPSBtZF9kZixieS54PSJyb3cubmFtZXMiLGJ5Lnk9ImZ1bGxfbmFtZSIpCiAgCiAgcmV0dXJuKGxpc3QoCiAgICBtYXRyaXhfcmF3PWRhdGFfbWF0cml4X3JhdywKICAgIG1hdHJpeF9wY2E9bSwKICAgIHBlcmNlbnRWYXJfb2JqPXBlcmNlbnRWYXJfb2JqKSkKICAKfQoKYGBgCgoKCmBgYHtyfQojR2VuZXMgdmFyaWFiaWxpdHksIHR5cGljYWxseSBiaW9sb2d5IGRpZmZlcmVuY2UgYWNyb3NzIHNhbXBsZXMgaXMgc3Ryb25nZXIuLiBzbyBpdCBpcyBhbHNvIGRpZmZpY3VsdCB0byBjYXRjaC4uLgptX3BjYV90aWJpYSA8LSBydW5fcGNhX3N0cnVjdHVyaW5nKG1hdHJpeF9kYXRhID0gbWF0cml4X2NvdW50c190aWJpYSx0cmFuc3Bvc2UgPSBGQUxTRSxmaWx0ZXJfZW1wdHlfc2FtcGxlc19jb3VudHMgPSAzMCkKbV9wY2FfaGlwIDwtIHJ1bl9wY2Ffc3RydWN0dXJpbmcobWF0cml4X2RhdGEgPSBtYXRyaXhfY291bnRzX2hpcCx0cmFuc3Bvc2UgPSBGQUxTRSxmaWx0ZXJfZW1wdHlfc2FtcGxlc19jb3VudHMgPSAzMCkKCmBgYAoKCiMgUGxvdCB0aGUgUENBIGZ1bmN0aW9uCmBgYHtyfQpyZXF1aXJlKCJnZ3Bsb3QyIikKI3NoYXBlcwpwbG90X3RoZV9wY2EgPC0gZnVuY3Rpb24ocGNhX2RmLGNvbG9ycyxwY2EscGNiLHRpdGxlLHN1YnRpdGxlLGNvbG9yc19zZWxlY3Rpb24sc2hhcGVzLHNoYXBlc19zZWxlY3Rpb24sYWxwaGFzPTAuNix0ZXh0X2NvbHVtbj0iUm93Lm5hbWVzIixwZXJjZW50VmFyX29iaikgewogIAogIG4gPC0gZ2dwbG90KGRhdGEgPSBwY2FfZGYsYWVzKHggPSBwY2FfZGZbW3Bhc3RlMCgiUEMiLHN1YnN0cihwY2Esc3RhcnQgPSAzLHN0b3AgPSAzKSldXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gcGNhX2RmW1twYXN0ZTAoIlBDIixzdWJzdHIocGNiLHN0YXJ0ID0gMyxzdG9wID0gMykpXV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSBwY2FfZGZbW2NvbG9yc11dLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNoYXBlID0gcGNhX2RmW1tzaGFwZXNdXSkpCiAgIyBuIDwtIG4gKyBnZW9tX3BvaW50KHNpemU9NikKICBuIDwtIG4gKyBnZW9tX2ppdHRlcihwb3NpdGlvbiA9IHBvc2l0aW9uX2ppdHRlcih3aWR0aCA9IDAuMDAwMDAwMDAxLGhlaWdodCA9IDAuMDAwMDAwMDAxLHNlZWQgPSAxMjM0NTYpLHNpemU9NixhbHBoYT1hbHBoYXMpCiAgbiA8LSBuICsgbGFicyh0aXRsZT1wYXN0ZTAoIlBDQSAiLHRpdGxlKSwKICAgICAgICAgICAgICAgICNjb2xvciA9IHBhc3RlMChjb2xvcnMpLAogICAgICAgICAgICAgICAgI3NoYXBlID0gcGFzdGUwKHNoYXBlcyksCiAgICAgICAgICAgICAgICBzdWJ0aXRsZSA9IHBhc3RlMChzdWJ0aXRsZSwiIikpICsKICAgIHhsYWIocGFzdGUwKCJQQyIsc3Vic3RyKHBhc3RlMCgiUEMiLHN1YnN0cihwY2Esc3RhcnQgPSAzLHN0b3AgPSAzKSksc3RhcnQgPSAzLHN0b3AgPSAzKSwiOiAiLAogICAgICAgICAgICAgICAgcm91bmQocGVyY2VudFZhcl9vYmpbYXMubnVtZXJpYyhzdWJzdHIocGFzdGUwKCJQQyIsc3Vic3RyKHBjYSxzdGFydCA9IDMsc3RvcCA9IDMpKSxzdGFydCA9IDMsc3RvcCA9IDMpKV0gKiAxMDAsZGlnaXRzID0gMiksICIlIHZhcmlhbmNlIikpICsKICAgIHlsYWIocGFzdGUwKCJQQyIsc3Vic3RyKHBhc3RlMCgiUEMiLHN1YnN0cihwY2Isc3RhcnQgPSAzLHN0b3AgPSAzKSksc3RhcnQgPSAzLHN0b3AgPSAzKSwiOiAiLAogICAgICAgICAgICAgICAgcm91bmQocGVyY2VudFZhcl9vYmpbYXMubnVtZXJpYyhzdWJzdHIocGFzdGUwKCJQQyIsc3Vic3RyKHBjYixzdGFydCA9IDMsc3RvcCA9IDMpKSxzdGFydCA9IDMsc3RvcCA9IDMpKV0gKiAxMDAsZGlnaXRzID0gMiksICIlIHZhcmlhbmNlIikpCiAgbiA8LSBuICsgdGhlbWUocGFuZWwuZ3JpZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgICAgICAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJ0cmFuc3BhcmVudCIpLAogICAgICAgICAgICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJ0cmFuc3BhcmVudCIpLAogICAgICAgICAgICAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTE1KSwKICAgICAgICAgICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTEyKSkKICBuIDwtIG4gKyBnZW9tX3RleHQoYWVzKGxhYmVsID0gcGNhX2RmW1t0ZXh0X2NvbHVtbl1dKSxjb2xvciA9ICJibGFjayIsIHNpemUgPSAyKQoKICAjIG4gPC0gbiArIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjb2xvcnNfc2VsZWN0aW9uKQogICMgbiA8LSBuICsgc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcyA9IHNoYXBlc19zZWxlY3Rpb24pCiAgbgogIAp9CmBgYAoKCiMgLS0tIFJhdwoKIyBUaWJpYQpgYGB7cixmaWcud2lkdGg9NixmaWcuaGVpZ2h0PTN9CiMjIyBOZWVkIHRvIGJlIHJ1biB0aGUgcnVuX3BjYV9zdHJ1Y3R1cmluZyBiZWZvcmUgdGhlIHBsb3QgdGhlIHBjYSBvdGhlcndpc2UgdGhlIG9iamVjdHMgbWVzcyB1cAojIEdlbmVyYXRlIHRoZSBjb2x1bW5zIGluIHRoZSBtZF9kZgpwbG90X3RoZV9wY2EocGNhX2RmID0gbV9wY2FfdGliaWEkbWF0cml4X3BjYSwKICAgICAgICAgICAgIHBlcmNlbnRWYXJfb2JqID0gbV9wY2FfdGliaWEkcGVyY2VudFZhcl9vYmosCiAgICAgICAgICAgICBjb2xvcnMgPSAgInRpc3N1ZV9jZWxsdHlwZV9sb3dlcmNhc2UiLHNoYXBlcyA9ICJoZWFsdGhfc3RhdHVzIiwKICAgICAgICAgICAgIHBjYSA9ICJQQzEiLHBjYiA9ICJQQzIiLAogICAgICAgICAgICAgdGl0bGU9IlBDQSBvZiBSTkEtc2VxIFJhdyBEYXRhIixzdWJ0aXRsZSA9ICJUaWJpYXMgU1ZGIGFuZCBBZGlwb2N5dGVzIiwKICAgICAgICAgICAgIHRleHRfY29sdW1uID0gInNhbXBsZV9udW1iZXIiKQoKYGBgCgoKCiMgSGlwCmBgYHtyLGZpZy53aWR0aD02LGZpZy5oZWlnaHQ9M30KIyMjIE5lZWQgdG8gYmUgcnVuIHRoZSBydW5fcGNhX3N0cnVjdHVyaW5nIGJlZm9yZSB0aGUgcGxvdCB0aGUgcGNhIG90aGVyd2lzZSB0aGUgb2JqZWN0cyBtZXNzIHVwCiMgR2VuZXJhdGUgdGhlIGNvbHVtbnMgaW4gdGhlIG1kX2RmCnBsb3RfdGhlX3BjYShwY2FfZGYgPSBtX3BjYV9oaXAkbWF0cml4X3BjYSwKICAgICAgICAgICAgIHBlcmNlbnRWYXJfb2JqID0gbV9wY2FfaGlwJHBlcmNlbnRWYXJfb2JqLAogICAgICAgICAgICAgY29sb3JzID0gICJ0aXNzdWVfY2VsbHR5cGVfbG93ZXJjYXNlIixzaGFwZXMgPSAiaGVhbHRoX3N0YXR1cyIsCiAgICAgICAgICAgICBwY2EgPSAiUEMxIixwY2IgPSAiUEMyIiwKICAgICAgICAgICAgIHRpdGxlPSJQQ0Egb2YgUk5BLXNlcSBSYXcgRGF0YSIsc3VidGl0bGUgPSAiSGlwcyBTVkYgYW5kIEFkaXBvY3l0ZXMiLAogICAgICAgICAgICAgdGV4dF9jb2x1bW4gPSAic2FtcGxlX251bWJlciIpCmBgYAoKCmBgYHtyfQptX3BjYV90aWJpYV90IDwtIHJ1bl9wY2Ffc3RydWN0dXJpbmcobWF0cml4X2RhdGEgPSBtYXRyaXhfY291bnRzX3RpYmlhLHRyYW5zcG9zZSA9IFRSVUUsZmlsdGVyX2VtcHR5X3NhbXBsZXNfY291bnRzID0gMzApCm1fcGNhX2hpcF90IDwtIHJ1bl9wY2Ffc3RydWN0dXJpbmcobWF0cml4X2RhdGEgPSBtYXRyaXhfY291bnRzX2hpcCx0cmFuc3Bvc2UgPSBUUlVFLGZpbHRlcl9lbXB0eV9zYW1wbGVzX2NvdW50cyA9IDMwKQoKYGBgCgojIFRpYmlhCmBgYHtyLGZpZy53aWR0aD02LGZpZy5oZWlnaHQ9M30KIyMjIE5lZWQgdG8gYmUgcnVuIHRoZSBydW5fcGNhX3N0cnVjdHVyaW5nIGJlZm9yZSB0aGUgcGxvdCB0aGUgcGNhIG90aGVyd2lzZSB0aGUgb2JqZWN0cyBtZXNzIHVwCiMgR2VuZXJhdGUgdGhlIGNvbHVtbnMgaW4gdGhlIG1kX2RmCnBsb3RfdGhlX3BjYShwY2FfZGYgPSBtX3BjYV90aWJpYV90JG1hdHJpeF9wY2EsCiAgICAgICAgICAgICBwZXJjZW50VmFyX29iaiA9IG1fcGNhX3RpYmlhX3QkcGVyY2VudFZhcl9vYmosCiAgICAgICAgICAgICBjb2xvcnMgPSAgInRpc3N1ZV9jZWxsdHlwZV9sb3dlcmNhc2UiLHNoYXBlcyA9ICJoZWFsdGhfc3RhdHVzIiwKICAgICAgICAgICAgIHBjYSA9ICJQQzEiLHBjYiA9ICJQQzIiLAogICAgICAgICAgICAgdGl0bGU9IlBDQSBvZiBSTkEtc2VxIFJhdyBEYXRhIixzdWJ0aXRsZSA9ICJUaWJpYXMgU1ZGIGFuZCBBZGlwb2N5dGUgVHJhbnNwb3NlZCIsCiAgICAgICAgICAgICB0ZXh0X2NvbHVtbiA9ICJzYW1wbGVfbnVtYmVyIikKCmBgYAojIEhpcApgYGB7cixmaWcud2lkdGg9NixmaWcuaGVpZ2h0PTN9CiMjIyBOZWVkIHRvIGJlIHJ1biB0aGUgcnVuX3BjYV9zdHJ1Y3R1cmluZyBiZWZvcmUgdGhlIHBsb3QgdGhlIHBjYSBvdGhlcndpc2UgdGhlIG9iamVjdHMgbWVzcyB1cAojIEdlbmVyYXRlIHRoZSBjb2x1bW5zIGluIHRoZSBtZF9kZgpwbG90X3RoZV9wY2EocGNhX2RmID0gbV9wY2FfaGlwX3QkbWF0cml4X3BjYSwKICAgICAgICAgICAgIHBlcmNlbnRWYXJfb2JqID0gbV9wY2FfaGlwX3QkcGVyY2VudFZhcl9vYmosCiAgICAgICAgICAgICBjb2xvcnMgPSAgInRpc3N1ZV9jZWxsdHlwZV9sb3dlcmNhc2UiLHNoYXBlcyA9ICJoZWFsdGhfc3RhdHVzIiwKICAgICAgICAgICAgIHBjYSA9ICJQQzEiLHBjYiA9ICJQQzIiLAogICAgICAgICAgICAgdGl0bGU9IlBDQSBvZiBSTkEtc2VxIFJhdyBEYXRhIiwKICAgICAgICAgICAgIHN1YnRpdGxlID0gIkhpcHMgU1ZGIGFuZCBBZGlwb2N5dGUgVHJhbnNwb3NlZCIsCiAgICAgICAgICAgICB0ZXh0X2NvbHVtbiA9ICJzYW1wbGVfbnVtYmVyIikKCmBgYAoKCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMgICAgIFRpYmlhIEFkaXBvY3l0ZXMgICAgICAjCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCmBgYHtyLGZpZy53aWR0aD02LGZpZy5oZWlnaHQ9M30KbV9wY2FfdGliaWFfdHJhbnNwb3NlZF9hZGlwb2N5dGVzIDwtIHJ1bl9wY2Ffc3RydWN0dXJpbmcobWF0cml4X2RhdGEgPSBtYXRyaXhfY291bnRzX3RpYmlhIHw+IGRwbHlyOjpzZWxlY3QoIkdlbmVfaWQiLCJHZW5lX25hbWUiLGVuZHNfd2l0aCgiYWRpcG9jeXRlIikpLHRyYW5zcG9zZSA9IFRSVUUsZmlsdGVyX2VtcHR5X3NhbXBsZXNfY291bnRzID0gMzApCgpwbG90X3RoZV9wY2EocGNhX2RmID0gbV9wY2FfdGliaWFfdHJhbnNwb3NlZF9hZGlwb2N5dGVzJG1hdHJpeF9wY2EsCiAgICAgICAgICAgICBwZXJjZW50VmFyX29iaiA9IG1fcGNhX3RpYmlhX3RyYW5zcG9zZWRfYWRpcG9jeXRlcyRwZXJjZW50VmFyX29iaiwKICAgICAgICAgICAgIGNvbG9ycyA9ICAidGlzc3VlX2NlbGx0eXBlX2xvd2VyY2FzZSIsCiAgICAgICAgICAgICBzaGFwZXMgPSAiaGVhbHRoX3N0YXR1cyIsCiAgICAgICAgICAgICBwY2EgPSAiUEMxIixwY2IgPSAiUEMyIiwKICAgICAgICAgICAgIHRpdGxlPSJQQ0Egb2YgUk5BLXNlcSBSYXcgRGF0YSIsc3VidGl0bGUgPSAiVGliaWFzIEFkaXBvY3l0ZXMgVHJhbnNwb3NlZCIsCiAgICAgICAgICAgICB0ZXh0X2NvbHVtbiA9ICJzYW1wbGVfbnVtYmVyIikKCgoKIyBJc3N1ZWQgc2FtcGxlcyB3aXRoIGxvdyBudW1iZXIgb2YgZ2VuZXMgcGVyIHNhbXBsZSBmcm9tIEhUTUwgcmVwb3J0CiMxMDcgdGliaWEgbm9uIHNjbGVyb3RpYyBhZGlwb2N5dGUKIzEwNyB0aWJpYSBzY2xlcm90aWMgYWRpcG9jeXRlCiMjOTkgdGliaWEgc2NsZXJvdGljIGFkaXBvY3l0ZQoKCiM4MCB0aWJpYSBub24gc2NsZXJvdGljIHBlbGxldAojMTYzIHRpYmlhIHNjbGVyb3RpYyBwZWxsZXQKYGBgCgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwojICAgICBUaWJpYSBTVkYvUGVsbGV0ICAgICAgIwojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwpgYGB7cixmaWcud2lkdGg9NixmaWcuaGVpZ2h0PTN9Cm1fcGNhX3RpYmlhX3RyYW5zcG9zZWRfcGVsbGV0IDwtIHJ1bl9wY2Ffc3RydWN0dXJpbmcobWF0cml4X2RhdGEgPSBtYXRyaXhfY291bnRzX3RpYmlhIHw+IGRwbHlyOjpzZWxlY3QoIkdlbmVfaWQiLCJHZW5lX25hbWUiLGVuZHNfd2l0aCgicGVsbGV0IikpLHRyYW5zcG9zZSA9IFRSVUUsZmlsdGVyX2VtcHR5X3NhbXBsZXNfY291bnRzID0gMzApCgoKcGxvdF90aGVfcGNhKHBjYV9kZiA9IG1fcGNhX3RpYmlhX3RyYW5zcG9zZWRfcGVsbGV0JG1hdHJpeF9wY2EsCiAgICAgICAgICAgICBwZXJjZW50VmFyX29iaiA9IG1fcGNhX3RpYmlhX3RyYW5zcG9zZWRfcGVsbGV0JHBlcmNlbnRWYXJfb2JqLAogICAgICAgICAgICAgY29sb3JzID0gICJ0aXNzdWVfY2VsbHR5cGVfbG93ZXJjYXNlIiwKICAgICAgICAgICAgIHNoYXBlcyA9ICJoZWFsdGhfc3RhdHVzIiwKICAgICAgICAgICAgIHBjYSA9ICJQQzEiLHBjYiA9ICJQQzIiLAogICAgICAgICAgICAgdGl0bGU9IlBDQSBvZiBSTkEtc2VxIFJhdyBEYXRhIixzdWJ0aXRsZSA9ICJUaWJpYXMgUGVsbGV0IFRyYW5zcG9zZWQiLAogICAgICAgICAgICAgdGV4dF9jb2x1bW4gPSAic2FtcGxlX251bWJlciIpCgojIElzc3VlZCBzYW1wbGVzIHdpdGggbG93IG51bWJlciBvZiBnZW5lcyBwZXIgc2FtcGxlIGZyb20gSFRNTCByZXBvcnQKCiM4MCB0aWJpYSBub24gc2NsZXJvdGljIHBlbGxldAojMTYzIHRpYmlhIHNjbGVyb3RpYyBwZWxsZXQKYGBgCgpgYGB7cn0KCmBgYAojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwojICAgICBIaXAgQWRpcG9jeXRlcyAgICAgICAgIwojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwpgYGB7cixmaWcud2lkdGg9NixmaWcuaGVpZ2h0PTN9Cm1fcGNhX2hpcF90cmFuc3Bvc2VkX2FkaXBvY3l0ZXMgPC0gcnVuX3BjYV9zdHJ1Y3R1cmluZyhtYXRyaXhfZGF0YSA9IG1hdHJpeF9jb3VudHNfaGlwIHw+IGRwbHlyOjpzZWxlY3QoIkdlbmVfaWQiLCJHZW5lX25hbWUiLGVuZHNfd2l0aCgiYWRpcG9jeXRlIikpLHRyYW5zcG9zZSA9IFRSVUUsZmlsdGVyX2VtcHR5X3NhbXBsZXNfY291bnRzID0gMzApCgpwbG90X3RoZV9wY2EocGNhX2RmID0gbV9wY2FfaGlwX3RyYW5zcG9zZWRfYWRpcG9jeXRlcyRtYXRyaXhfcGNhLAogICAgICAgICAgICAgcGVyY2VudFZhcl9vYmogPSBtX3BjYV9oaXBfdHJhbnNwb3NlZF9hZGlwb2N5dGVzJHBlcmNlbnRWYXJfb2JqLAogICAgICAgICAgICAgY29sb3JzID0gICJ0aXNzdWVfY2VsbHR5cGVfbG93ZXJjYXNlIiwKICAgICAgICAgICAgIHNoYXBlcyA9ICJoZWFsdGhfc3RhdHVzIiwKICAgICAgICAgICAgIHBjYSA9ICJQQzEiLHBjYiA9ICJQQzIiLAogICAgICAgICAgICAgdGl0bGU9IlBDQSBvZiBSTkEtc2VxIFJhdyBEYXRhIixzdWJ0aXRsZSA9ICJIaXBzIEFkaXBvY3l0ZXMgVHJhbnNwb3NlZCIsCiAgICAgICAgICAgICB0ZXh0X2NvbHVtbiA9ICJzYW1wbGVfbnVtYmVyIikKCgoKIyBJc3N1ZWQgc2FtcGxlcyB3aXRoIGxvdyBudW1iZXIgb2YgZ2VuZXMgcGVyIHNhbXBsZSBmcm9tIEhUTUwgcmVwb3J0LCBleHBlY3RlZCB0byBiZSBhbHNvIGFzc29jaWF0ZWQgd2l0aCBsb3cgbnVtYmVyIG9mIHNlcXVlbmNpbmcgcmVhZCBwZXIgc2FtcGxlLi4uCiM3NCBoaXAgbm9uIHNjbGVyb3RpYyBhZGlwb2N5dGUKIzc5IGhpcCBub24gc2NsZXJvdGljIGFkaXBvY3l0ZQojMTUwIGhpcCBub24gc2NsZXJvdGljIGFkaXBvY3l0ZQoKIzc0IGhpcCBzY2xlcm90aWMgYWRpcG9jeXRlCiM3OSBoaXAgc2NsZXJvdGljIGFkaXBvY3l0ZQoKIzc4IGhpcCBub24gc2NsZXJvdGljIGFkaXBvY3l0ZQojNzggaGlwIHNjbGVyb3RpYyBhZGlwb2N5dGUKCmBgYAoKCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMgICAgIEhpcCBTVkYvUGVsbGV0ICAgICAgIwojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwpgYGB7cixmaWcud2lkdGg9NixmaWcuaGVpZ2h0PTN9Cm1fcGNhX2hpcF90cmFuc3Bvc2VkX3BlbGxldCA8LSBydW5fcGNhX3N0cnVjdHVyaW5nKG1hdHJpeF9kYXRhID0gbWF0cml4X2NvdW50c19oaXAgfD4gZHBseXI6OnNlbGVjdCgiR2VuZV9pZCIsIkdlbmVfbmFtZSIsZW5kc193aXRoKCJwZWxsZXQiKSksdHJhbnNwb3NlID0gVFJVRSxmaWx0ZXJfZW1wdHlfc2FtcGxlc19jb3VudHMgPSAzMCkKCgpwbG90X3RoZV9wY2EocGNhX2RmID0gbV9wY2FfaGlwX3RyYW5zcG9zZWRfcGVsbGV0JG1hdHJpeF9wY2EsCiAgICAgICAgICAgICBwZXJjZW50VmFyX29iaiA9IG1fcGNhX2hpcF90cmFuc3Bvc2VkX3BlbGxldCRwZXJjZW50VmFyX29iaiwKICAgICAgICAgICAgIGNvbG9ycyA9ICAidGlzc3VlX2NlbGx0eXBlX2xvd2VyY2FzZSIsCiAgICAgICAgICAgICBzaGFwZXMgPSAiaGVhbHRoX3N0YXR1cyIsCiAgICAgICAgICAgICBwY2EgPSAiUEMxIixwY2IgPSAiUEMyIiwKICAgICAgICAgICAgIHRpdGxlPSJQQ0Egb2YgUk5BLXNlcSBSYXcgRGF0YSIsc3VidGl0bGUgPSAiSGlwcyBQZWxsZXQgVHJhbnNwb3NlZCIsCiAgICAgICAgICAgICB0ZXh0X2NvbHVtbiA9ICJzYW1wbGVfbnVtYmVyIikKCiMgSXNzdWVkIHNhbXBsZXMgd2l0aCBsb3cgbnVtYmVyIG9mIGdlbmVzIHBlciBzYW1wbGUgZnJvbSBIVE1MIHJlcG9ydAoKIAojNzQgSGlwIG5vbiBzY2xlcm90aWMgcGVsbGV0CiM3NCBIaXAgc2NsZXJvdGljIHBlbGxldAojNzggaGlwIG5vbi5zY2xlcm90aWMgcGVsbGV0CiM3OCBoaXAgc2NsZXJvdGljIHBlbGxldApgYGAKCmBgYHtyfQptZF9kZgpgYGAKCgpgYGB7cn0KcGxvdF90aGVfcGNhKHBjYV9kZiA9IG1fcGNhX2hpcF90cmFuc3Bvc2VkX3BlbGxldCRtYXRyaXhfcGNhLAogICAgICAgICAgICAgcGVyY2VudFZhcl9vYmogPSBtX3BjYV9oaXBfdHJhbnNwb3NlZF9wZWxsZXQkcGVyY2VudFZhcl9vYmosCiAgICAgICAgICAgICBjb2xvcnMgPSAgInRpc3N1ZV9jZWxsdHlwZV9sb3dlcmNhc2UiLAogICAgICAgICAgICAgc2hhcGVzID0gImhlYWx0aF9zdGF0dXMiLAogICAgICAgICAgICAgcGNhID0gIlBDMSIscGNiID0gIlBDMiIsCiAgICAgICAgICAgICB0aXRsZT0iUENBIG9mIFJOQS1zZXEgUmF3IERhdGEiLHN1YnRpdGxlID0gIkhpcHMgUGVsbGV0IFRyYW5zcG9zZWQiLAogICAgICAgICAgICAgdGV4dF9jb2x1bW4gPSAiQWdlIikKYGBgCgpgYGB7cn0KcGxvdF90aGVfcGNhKHBjYV9kZiA9IG1fcGNhX2hpcF90cmFuc3Bvc2VkX3BlbGxldCRtYXRyaXhfcGNhLAogICAgICAgICAgICAgcGVyY2VudFZhcl9vYmogPSBtX3BjYV9oaXBfdHJhbnNwb3NlZF9wZWxsZXQkcGVyY2VudFZhcl9vYmosCiAgICAgICAgICAgICBjb2xvcnMgPSAgIkdlbmRlciIsCiAgICAgICAgICAgICBzaGFwZXMgPSAiaGVhbHRoX3N0YXR1cyIsCiAgICAgICAgICAgICBwY2EgPSAiUEMxIixwY2IgPSAiUEMyIiwKICAgICAgICAgICAgIHRpdGxlPSJQQ0Egb2YgUk5BLXNlcSBSYXcgRGF0YSIsc3VidGl0bGUgPSAiSGlwcyBQZWxsZXQgVHJhbnNwb3NlZCIsCiAgICAgICAgICAgICB0ZXh0X2NvbHVtbiA9ICJBZ2UiKQpgYGAKCiMgVGVzdCBvZiBRQyBmb3Igc2FtcGxlcyAKIyMgUmVtb3ZlIGlmIGFyZSBhd2F5IGZvciBjb21wbGV4aXR5IG9yIG51bWJlciBvZiBnZW5lcy4KCmBgYHtyfQptX3BjYV90aWJpYSRtYXRyaXhfcmF3CmBgYAojIyMgUGxvdCB0aGUgbnVtYmVyIG9mIHJlYWRzIHBlciBzYW1wbGUgZnJvbSByYXcgbWF0cml4IG9mIHRpYmlhLgpgYGB7cixmaWcud2lkdGg9MjUsZmlnLmhlaWdodD05fQojbWF0cml4X2NvdW50c190aWJpYQojbV9wY2FfdGliaWEkbWF0cml4X3JhdwoKc3Vtc19tbSA9IGNvbFN1bXMobV9wY2FfdGliaWEkbWF0cml4X3Jhd1szOm5jb2wobV9wY2FfdGliaWEkbWF0cml4X3JhdyldKQpzdW1zX21tIDwtIGRhdGEuZnJhbWUoQ29sdW1uID0gY29sbmFtZXMobV9wY2FfdGliaWEkbWF0cml4X3Jhd1szOm5jb2wobV9wY2FfdGliaWEkbWF0cml4X3JhdyldKSwgU3VtID0gc3Vtc19tbSkKc3Vtc19tbSRDb2x1bW4gPC10b2xvd2VyKHN1bXNfbW0kQ29sdW1uKQoKCgojIENhdGVnb3JpemUgdGhlIGdyb3VwcyBiYXNlZCBvbiB0aGUgQ29sdW1uIG5hbWVzCnN1bXNfbW0kR3JvdXAgPC0gaWZlbHNlKGdyZXBsKCJ0aWJpYV9ub24uc2NsZXJvdGljX2FkaXBvY3l0ZSIsIHN1bXNfbW0kQ29sdW1uKSwgIlROU0EiLAogICAgICAgICAgICAgICAgICAgaWZlbHNlKGdyZXBsKCJ0aWJpYV9zY2xlcm90aWNfYWRpcG9jeXRlIiwgc3Vtc19tbSRDb2x1bW4pLCAiVFNBIiwKICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoZ3JlcGwoInRpYmlhX25vbi5zY2xlcm90aWNfcGVsbGV0Iiwgc3Vtc19tbSRDb2x1bW4pLCAiVE5TUCIsICJUU1AiKSkpCgpzdW1zX21tCiMgQ3JlYXRlIGEgY3VzdG9tIGNvbG9yIHBhbGV0dGUKY29sb3JfcGFsZXR0ZSA8LSBjKCJUTlNBIiA9ICIjMDAyOTZiIiwgIlRTQSIgPSAiIzFlOTFkMCIsICJUTlNQIiA9ICIjZmFhODE5IiwiVFNQIj0iI2YzNzUyMCIpCmBgYAoKCmBgYHtyLGZpZy53aWR0aD0yOSxmaWcuaGVpZ2h0PTE0fQpsaWJyYXJ5KGdncGxvdDIpCm1lYW5fc3VtIDwtIG1lYW4oc3Vtc19tbSRTdW0pCnF1YW50aWxlcyA8LSBxdWFudGlsZShzdW1zX21tJFN1bSwgcHJvYnMgPSBjKDAuMjUsIDAuNzUsMC45MCkpCgpwIDwtIGdncGxvdChzdW1zX21tLCBhZXMoeCA9IHJlb3JkZXIoQ29sdW1uLCBTdW0pLCB5ID0gU3VtLCBmaWxsID0gR3JvdXApKSArCiNnZ3Bsb3Qoc3Vtc19tbSwgYWVzKHggPSBDb2x1bW4sIHkgPSBTdW0sIGZpbGwgPSBHcm91cCkpICsKICAKCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsKICBsYWJzKHRpdGxlID0gIkNvdW50cyBTdW1zIiwKICAgICAgIHggPSAiU2FtcGxlcyIsCiAgICAgICB5ID0gIlN1bSBvZiBhbGwgY291bnRzIikgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGNvbG9yX3BhbGV0dGUpICsKICBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0ID0gbWVhbl9zdW0sIGNvbG9yID0gIk1lYW4iKSwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0ID0gcXVhbnRpbGVzWzFdLCBjb2xvciA9ICIyNXRoIFBlcmNlbnRpbGUiKSwgbGluZXR5cGUgPSAiZG90dGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0ID0gcXVhbnRpbGVzWzJdLCBjb2xvciA9ICI3NXRoIFBlcmNlbnRpbGUiKSwgbGluZXR5cGUgPSAiZG90dGVkIiwgc2l6ZSA9IDEpICsKICBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0ID0gcXVhbnRpbGVzWzNdLCBjb2xvciA9ICI5MHRoIFBlcmNlbnRpbGUiKSwgbGluZXR5cGUgPSAiZG90dGVkIiwgc2l6ZSA9IDEpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygicmVkIiwgImJsdWUiLCAiZ3JlZW4iLCIjOTAzNDk4IiksCiAgICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IGMoIk1lYW4iLCAiMjV0aCBQZXJjZW50aWxlIiwgIjc1dGggUGVyY2VudGlsZSIsICI5MHRoIFBlcmNlbnRpbGUiKSwKICAgICAgICAgICAgICAgICAgICAgbmFtZSA9ICJTdGF0aXN0aWNzIikgKyAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgaGp1c3QgPSAxKSwKICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLAogICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksICAjIFJlbW92ZSBwYW5lbCBiYWNrZ3JvdW5kCiAgICAgICAgcGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKSwgICMgUmVtb3ZlIG1ham9yIGdyaWQgbGluZXMKICAgICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLCAgIyBSZW1vdmUgbWlub3IgZ3JpZCBsaW5lcwogICAgICAgICkgICMgUm90YXRlIHgtYXhpcyBsYWJlbHMgZm9yIGJldHRlciB2aXNpYmlsaXR5CgpwbG90bHk6OmdncGxvdGx5KHApCmBgYAojIFRJQklBIFNhbXBsZXMgb3V0CgojWDE2MyAgIFRTUAojWDk5ICAgIFRTQQojWDEwNyAgIFROU0EgVFNBIFROU1AKI1g4MCAgICBUTlNQIFROU0EgVFNQCiNYMTA1ICAgVFNQIFROU1AKI1gxNDggICBUU1AKI1gxMDQgICBUU0EgVFNQCiNYMTY0ICAgVFNBIAojWDEwOSAgIFROU1AKIyB3ZSBmaWx0ZXIgb3V0IGFyb3VuZCBzYW1lIHByb3BvcnRpb25zIGlmIDI1JSBpbiBUSUJJQSBpcyBhcm91bmQgNzAwayB3ZSBmaWx0ZXJlZCA0MDcyNjUgYW5kIGluIEhJUCAyNSUgaXMgMU0gaW4gSGlwLCB3ZSBmaWx0ZXJkIDc5MUsKCgpgYGB7cn0Kc3Vtc19tbSB8PiBkcGx5cjo6ZmlsdGVyKFN1bSA8IDQwNzI2NSkKc3Vtc19tbV90aWJpYSA8LSBzdW1zX21tIHw+IGRwbHlyOjpmaWx0ZXIoIVN1bSA8IDQwNzI2NSkKYGBgCgoKCgojIEhJUAoKYGBge3J9Cm1fcGNhX2hpcCRtYXRyaXhfcmF3CmBgYAojIyMgUGxvdCB0aGUgbnVtYmVyIG9mIHJlYWRzIHBlciBzYW1wbGUgZnJvbSByYXcgbWF0cml4IG9mIHRpYmlhLgpgYGB7cixmaWcud2lkdGg9MjUsZmlnLmhlaWdodD05fQojbWF0cml4X2NvdW50c19oaXAKI21fcGNhX2hpcCRtYXRyaXhfcmF3CnN1bXNfbW0gPSBjb2xTdW1zKG1fcGNhX2hpcCRtYXRyaXhfcmF3WzM6bmNvbChtX3BjYV9oaXAkbWF0cml4X3JhdyldKQpzdW1zX21tIDwtIGRhdGEuZnJhbWUoQ29sdW1uID0gY29sbmFtZXMobV9wY2FfaGlwJG1hdHJpeF9yYXdbMzpuY29sKG1fcGNhX2hpcCRtYXRyaXhfcmF3KV0pLCBTdW0gPSBzdW1zX21tKQoKCnN1bXNfbW0kQ29sdW1uIDwtdG9sb3dlcihzdW1zX21tJENvbHVtbikKCgojIENhdGVnb3JpemUgdGhlIGdyb3VwcyBiYXNlZCBvbiB0aGUgQ29sdW1uIG5hbWVzCnN1bXNfbW0kR3JvdXAgPC0gaWZlbHNlKGdyZXBsKCJoaXBfbm9uLnNjbGVyb3RpY19hZGlwb2N5dGUiLCBzdW1zX21tJENvbHVtbiksICJITlNBIiwKICAgICAgICAgICAgICAgICAgIGlmZWxzZShncmVwbCgiaGlwX3NjbGVyb3RpY19hZGlwb2N5dGUiLCBzdW1zX21tJENvbHVtbiksICJIU0EiLAogICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShncmVwbCgiaGlwX25vbi5zY2xlcm90aWNfcGVsbGV0Iiwgc3Vtc19tbSRDb2x1bW4pLCAiSE5TUCIsICJIU1AiKSkpCgpzdW1zX21tCiMgQ3JlYXRlIGEgY3VzdG9tIGNvbG9yIHBhbGV0dGUKY29sb3JfcGFsZXR0ZSA8LSBjKCJITlNBIiA9ICIjMDAyOTZiIiwgIkhTQSIgPSAiIzFlOTFkMCIsICJITlNQIiA9ICIjZmFhODE5IiwiSFNQIj0iI2YzNzUyMCIpCmBgYAoKCmBgYHtyLGZpZy53aWR0aD0yNSxmaWcuaGVpZ2h0PTl9CmxpYnJhcnkoZ2dwbG90MikKYyA8LSBtZWFuKHN1bXNfbW0kU3VtKQpxdWFudGlsZXMgPC0gcXVhbnRpbGUoc3Vtc19tbSRTdW0sIHByb2JzID0gYygwLjI1LCAwLjc1LDAuOTApKQoKcCA8LSBnZ3Bsb3Qoc3Vtc19tbSwgYWVzKHggPSByZW9yZGVyKENvbHVtbiwgU3VtKSwgeSA9IFN1bSwgZmlsbCA9IEdyb3VwKSkgKwojZ2dwbG90KHN1bXNfbW0sIGFlcyh4ID0gQ29sdW1uLCB5ID0gU3VtLCBmaWxsID0gR3JvdXApKSArCiAgCgogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgbGFicyh0aXRsZSA9ICJDb3VudHMgU3VtcyIsCiAgICAgICB4ID0gIlNhbXBsZXMiLAogICAgICAgeSA9ICJTdW0gb2YgYWxsIGNvdW50cyIpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjb2xvcl9wYWxldHRlKSArCiAgZ2VvbV9obGluZShhZXMoeWludGVyY2VwdCA9IG1lYW5fc3VtLCBjb2xvciA9ICJNZWFuIiksIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV9obGluZShhZXMoeWludGVyY2VwdCA9IHF1YW50aWxlc1sxXSwgY29sb3IgPSAiMjV0aCBQZXJjZW50aWxlIiksIGxpbmV0eXBlID0gImRvdHRlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV9obGluZShhZXMoeWludGVyY2VwdCA9IHF1YW50aWxlc1syXSwgY29sb3IgPSAiNzV0aCBQZXJjZW50aWxlIiksIGxpbmV0eXBlID0gImRvdHRlZCIsIHNpemUgPSAxKSArCiAgZ2VvbV9obGluZShhZXMoeWludGVyY2VwdCA9IHF1YW50aWxlc1szXSwgY29sb3IgPSAiOTB0aCBQZXJjZW50aWxlIiksIGxpbmV0eXBlID0gImRvdHRlZCIsIHNpemUgPSAxKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoInJlZCIsICJibHVlIiwgImdyZWVuIiwiIzkwMzQ5OCIpLAogICAgICAgICAgICAgICAgICAgICBicmVha3MgPSBjKCJNZWFuIiwgIjI1dGggUGVyY2VudGlsZSIsICI3NXRoIFBlcmNlbnRpbGUiLCAiOTB0aCBQZXJjZW50aWxlIiksCiAgICAgICAgICAgICAgICAgICAgIG5hbWUgPSAiU3RhdGlzdGljcyIpICsgIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIGhqdXN0ID0gMSksCiAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwKICAgICAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLCAgIyBSZW1vdmUgcGFuZWwgYmFja2dyb3VuZAogICAgICAgIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2JsYW5rKCksICAjIFJlbW92ZSBtYWpvciBncmlkIGxpbmVzCiAgICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwgICMgUmVtb3ZlIG1pbm9yIGdyaWQgbGluZXMKICAgICAgICApICAjIFJvdGF0ZSB4LWF4aXMgbGFiZWxzIGZvciBiZXR0ZXIgdmlzaWJpbGl0eQoKcGxvdGx5OjpnZ3Bsb3RseShwKQpgYGAKIyBISVAgU2FtcGxlcyBvdXQKIyMjIyNYNzggLSA0CiMjIyMjWDc0IC00CiMjIyMjWDc5IC0yIEhOU0EgYW5kIEhTQQojIyMjI1gxNTAgSE5TQQojIyMjI1gxNTQgSE5TUAojIFJlbW92ZWQgYWxsIHRoZSBzYW1wbGVzIHdpdGggbGVzcyB0aGFuIDc5MTI4NiBjb3VudHMgaW4gSGlwLgoKIyBGaWx0ZXIgU2FtcGxlcwpgYGB7cn0Kc3Vtc19tbV9oaXAgPC0gc3Vtc19tbSB8PiBkcGx5cjo6ZmlsdGVyKCFTdW0gPCA3OTEyODYpCnN1bXNfbW0gfD4gZHBseXI6OmZpbHRlcihTdW0gPCA3OTEyODYpCnN1bXNfbW1faGlwCgpgYGAKCiMgRGlmZmVyZW50aWFsIGdlbmUgZXhwcmVzc2lvbi4KCiMjIFNlcGFyYXRlIHRoZSBkYXRhIGluIHNtYWxsZXIgZ3JvdXBzLgoKYGBge3J9CiN0aWJpYQoKI2hpcAoKI2FkaXBvCgojcGVsbGV0Cgojc2NsZXJvdGljCgojbm9uX3NjbGVyb3RpYwojIAojIHRpYmlhcy0+IHNjbGVyb3RpYyB2cyBuc2NsZXJvdGljCiMgaGlwLT4gc2NsZXJvdGljIHZzIG5zY2xlcm90aWMKIyAKIyBBZGlwb2N5dGUgLT4gdGliaWEgdnMgSGlwCiMgCiMgCiMgQWRpcG9jeXRlcwojIE5vbi1zY2xlcm90aWMgdnMgU2NsZXJvdGljIG9mIEhpcAojIE5vbi1zY2xlcm90aWMgdnMgU2NsZXJvdGljIG9mIFRpYmlhCiMgTm9uLXNjbGVyb3RpYyBUaWJpYSB2cyBOb24tc2NsZXJvdGljIEhpcAojIFNjbGVyb3RpYyBUaWJpYSB2cyBTY2xlcm90aWMgSGlwCiMgCiMgCiMgUGVsbGV0CiMgTm9uLXNjbGVyb3RpYyB2cyBTY2xlcm90aWMgb2YgSGlwCiMgTm9uLXNjbGVyb3RpYyB2cyBTY2xlcm90aWMgb2YgVGliaWEKIyBOb24tc2NsZXJvdGljIFRpYmlhIHZzIE5vbi1zY2xlcm90aWMgSGlwCiMgU2NsZXJvdGljIFRpYmlhIHZzIFNjbGVyb3RpYyBIaXAKIyAKIyBBZGlwb2N5dGVzIHZzIFBlbGxldCByZXN1bHRzIC0tPiBWZW5uIAojIE5vbiBzY2xlcm90aWMgYWxvbmUKIyBTY2xlcm90aWMgYWxvbmUKCmBgYAoKCiMgQ29tcGFyaXNvbnMKIyMjIFVzZSB0aGUgc2FtcGxlcyBjbGVhbmVkIG9iamVjdHMKc3Vtc19tbV90aWJpYQpzdW1zX21tX2hpcCAKCiMgZmlsdGVyIG91dCB0aGUgc2FtcGxlcyB3ZSByZW1vdmVkIGJlZm9yZQpgYGB7cn0KCnN1bXNfbW1fdGliaWEKc3Vtc19tbV9oaXAKI21hdHJpeF9jb3VudHNfdGliaWEKI21hdHJpeF9jb3VudHNfaGlwCgptX3BjYV90aWJpYSRtYXRyaXhfcmF3X2ZpbHRlcmVkX3NhbXBsZXNfZm9yX0RFRyA8LSBtX3BjYV90aWJpYSRtYXRyaXhfcmF3Wyxyb3duYW1lcyhzdW1zX21tX3RpYmlhKV0KbV9wY2FfaGlwJG1hdHJpeF9yYXdfZmlsdGVyZWRfc2FtcGxlc19mb3JfREVHIDwtIG1fcGNhX2hpcCRtYXRyaXhfcmF3Wyxyb3duYW1lcyhzdW1zX21tX2hpcCldCiN1c2luZyBkcGx5cgojbV9wY2FfdGliaWEkbWF0cml4X3Jhd19maWx0ZXJlZF9zYW1wbGVzX2Zvcl9ERUcgPC0gbV9wY2FfdGliaWEkbWF0cml4X3JhdyB8PiAgIHNlbGVjdChhbGxfb2Yocm93bmFtZXMoc3Vtc19tbV90aWJpYSkpKQoKCgoKCmBgYAojIyMjIyMjIyMjIyMjCiMjIyBFREdFUiAjIyMKIyMjIyMjIyMjIyMjIwoKIyMjIExSVDogU3VpdGFibGUgZm9yIGNvbXBsZXggZGVzaWducyBidXQgbWF5IG5vdCBmdWxseSBhY2NvdW50IGZvciB2YXJpYWJpbGl0eSwgcG90ZW50aWFsbHkgbGVhZGluZyB0byBpbmZsYXRlZCBmYWxzZSBwb3NpdGl2ZXMuCiMjIyBRTEY6IFByb3ZpZGVzIHJvYnVzdCByZXN1bHRzIGJ5IG1vZGVsaW5nIGV4dHJhIHZhcmlhYmlsaXR5IHRocm91Z2ggcXVhc2ktbGlrZWxpaG9vZCBtZXRob2RzIGFuZCBzaHJpbmthZ2UgZXN0aW1hdG9ycy4gSXQgeWllbGRzIG1vcmUgYWNjdXJhdGUgcC12YWx1ZXMgYW5kIGJldHRlciBjb250cm9sIG92ZXIgZmFsc2UgcG9zaXRpdmVzLgoKIyAtLS0gTm9ybWFsaXplCmBgYHtyLGZpZy53aWR0aD0xMixmaWcuaGVpZ2h0PTZ9CiMjIyMjIyMjIyMjIyMKIyAgIGVkZ2VSICAgIwojIyMjIyMjIyMjIyMjCmxpYnJhcnkoZGF0YS50YWJsZSkKbGlicmFyeShlZGdlUikKI1J1biBlZGdlUiBvbiB0aGUgQ09NQkFUc2VxIGJhdGNoIGNvcnJlY3RlZCBkYXRhLgptZXNzYWdlKCJCdWlsZHVpbmcgdGhlIERFRyBkYXRhIGxpc3QgZm9yIGVkZ2VSLiIpCgojLjEtIEJ1aWxkIERHRSBsaXN0IGFuZCBub3JtYWxpemUKeSA9IERHRUxpc3QoY291bnRzID0gbV9wY2FfdGliaWEkbWF0cml4X3Jhd19maWx0ZXJlZF9zYW1wbGVzX2Zvcl9ERUcsIGdyb3VwID0gc3Vtc19tbV90aWJpYSRHcm91cCwgZ2VuZXMgPSBtX3BjYV90aWJpYSRtYXRyaXhfcmF3WywyXSkKI3BlcmZvcm0gVE1NIG5vcm1hbGl6YXRpb24KbWVzc2FnZSgiTm9ybWFsaXppbmcgdXNpbmcgVE1NLlxuIikKeV9ub3JtIDwtIGNhbGNOb3JtRmFjdG9ycyhvYmplY3QgPSB5LG1ldGhvZCA9ICJUTU0iKQp5X25vcm1hbGl6ZWRfY29ycmVjdGVkIDwtIGNwbSh5ID0geV9ub3JtLG5vcm1hbGl6ZWQubGliLnNpemVzID0gVFJVRSkKcm93bmFtZXMoeV9ub3JtYWxpemVkX2NvcnJlY3RlZCkgPC0geSRnZW5lcyRnZW5lcwoKI3lfbm9ybWFsaXplZF9jb3JyZWN0ZWRfcGNhcyA8LSBwcmNvbXAobG9nMih5X25vcm1hbGl6ZWRfY29ycmVjdGVkICsgMSkpCnlfbm9ybWFsaXplZF9jb3JyZWN0ZWRfcGNhcyA8LSBwcmNvbXAoeV9ub3JtYWxpemVkX2NvcnJlY3RlZCxjZW50ZXIgPSBUUlVFLHNjYWxlLiA9IFRSVUUpCiNjYWxjdWxhdCB0aGUgUEMgIiUiJ3MKcGVyY2VudFZhcl9vYmogPC0geV9ub3JtYWxpemVkX2NvcnJlY3RlZF9wY2FzJHNkZXZeMi9zdW0oeV9ub3JtYWxpemVkX2NvcnJlY3RlZF9wY2FzJHNkZXZeMikKI1NhdmUgYXMgYSBkZgp5X25vcm1hbGl6ZWRfY29ycmVjdGVkX3BjYXNfZGYgPC0gYXMuZGF0YS5mcmFtZSh5X25vcm1hbGl6ZWRfY29ycmVjdGVkX3BjYXNbMl0kcm90YXRpb24pCnlfbm9ybWFsaXplZF9jb3JyZWN0ZWRfcGNhc19kZiA8LSBtZXJnZSh5X25vcm1hbGl6ZWRfY29ycmVjdGVkX3BjYXNfZGYsbWRfZjNwb3MsIGJ5LnggPSAicm93Lm5hbWVzIiwgYnkueSA9ICJTYW1wbGVzIikKIyB5X25vcm1hbGl6ZWRfY29ycmVjdGVkX3BjYXNfZGZbLGMoMSwxOCldCm1lc3NhZ2UoIkRvbmUiKQptZXNzYWdlKCJQbG90IHJlYWR5LiIpCgp5X25vcm1hbGl6ZWRfY29ycmVjdGVkX3BjYXNfZGYgPC0geV9ub3JtYWxpemVkX2NvcnJlY3RlZF9wY2FzX2RmIHw+IGRwbHlyOjptdXRhdGUoU2FtcGxlMiA9IHN1YigiXiguKj8pXFwuLioiLCAiXFwxIiwgU2FtcGxlKSkKeV9ub3JtYWxpemVkX2NvcnJlY3RlZF9wY2FzX2RmIDwtIHlfbm9ybWFsaXplZF9jb3JyZWN0ZWRfcGNhc19kZiB8PiBkcGx5cjo6bXV0YXRlKFNhbXBsZTMgPSBzdWIoIi4qP1xcLiguKikiLCAiXFwxIiwgU2FtcGxlKSkKCgoKZm9yIChjb2x1bW5fdG9fcGxvdCBpbiBjKCJFeHBlcmltZW50IiwiU2FtcGxlIiwiU2FtcGxlMiIsIlNhbXBsZTMiKSkgewogIHByaW50KHBsb3RseTo6Z2dwbG90bHkocGxvdF90aGVfcGNhKHBjYV9kZiA9IHlfbm9ybWFsaXplZF9jb3JyZWN0ZWRfcGNhc19kZixjb2xvcnMgPSBjb2x1bW5fdG9fcGxvdCxzaGFwZXMgPSAiQ2VsbHR5cGUiLHBjYSA9ICJQQzEiLCBwY2IgPSAiUEMyIix0aXRsZSA9ICIoTm9ybWFsaXplZCBUTU0pIixzdWJ0aXRsZSA9ICJISCBGM3BvcyBHRiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGV4dF9jb2x1bW4gPSAiQmF0Y2giLHBlcmNlbnRWYXJfb2JqID0gcGVyY2VudFZhcl9vYmopKSkKICB9CgpgYGAKCgoKYGBge3J9CmBgYAoKCmBgYHtyfQpgYGAKCgpgYGB7cn0KYGBgCgoKCg==